1
0
Fork 0
mirror of synced 2024-09-29 17:01:37 +13:00

Merge pull request #5443 from appwrite/1.3.x

Merge 1.3.x to Master
This commit is contained in:
Torsten Dittmann 2023-04-27 21:49:39 +02:00 committed by GitHub
commit c3ad6a1260
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 267 additions and 151 deletions

2
.gitmodules vendored
View file

@ -1,4 +1,4 @@
[submodule "app/console"] [submodule "app/console"]
path = app/console path = app/console
url = https://github.com/appwrite/console url = https://github.com/appwrite/console
branch = 2.3.3 branch = 2.3.4

View file

@ -1,3 +1,10 @@
# Version 1.3.2
## Bugs
- Fixed auto-setting custom ID on nested documents [#5363](https://github.com/appwrite/appwrite/pull/5363)
- Fixed listDocuments not returning all the documents [#5395](https://github.com/appwrite/appwrite/pull/5395)
- Fixed deleting keys, webhooks, platforms and domains after deleting project [#5395](https://github.com/appwrite/appwrite/pull/5395)
# Version 1.3.1 # Version 1.3.1
## Bugs ## Bugs

View file

@ -67,7 +67,7 @@ docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \ --volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \ --entrypoint="install" \
appwrite/appwrite:1.3.1 appwrite/appwrite:1.3.2
``` ```
### Windows ### Windows
@ -79,7 +79,7 @@ docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^ --volume //var/run/docker.sock:/var/run/docker.sock ^
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
--entrypoint="install" ^ --entrypoint="install" ^
appwrite/appwrite:1.3.1 appwrite/appwrite:1.3.2
``` ```
#### PowerShell #### PowerShell
@ -89,7 +89,7 @@ docker run -it --rm `
--volume /var/run/docker.sock:/var/run/docker.sock ` --volume /var/run/docker.sock:/var/run/docker.sock `
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ` --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
--entrypoint="install" ` --entrypoint="install" `
appwrite/appwrite:1.3.1 appwrite/appwrite:1.3.2
``` ```
运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。 运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。

View file

@ -76,7 +76,7 @@ docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \ --volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \ --entrypoint="install" \
appwrite/appwrite:1.3.1 appwrite/appwrite:1.3.2
``` ```
### Windows ### Windows
@ -88,7 +88,7 @@ docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^ --volume //var/run/docker.sock:/var/run/docker.sock ^
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
--entrypoint="install" ^ --entrypoint="install" ^
appwrite/appwrite:1.3.1 appwrite/appwrite:1.3.2
``` ```
#### PowerShell #### PowerShell
@ -98,7 +98,7 @@ docker run -it --rm `
--volume /var/run/docker.sock:/var/run/docker.sock ` --volume /var/run/docker.sock:/var/run/docker.sock `
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ` --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
--entrypoint="install" ` --entrypoint="install" `
appwrite/appwrite:1.3.1 appwrite/appwrite:1.3.2
``` ```
Once the Docker installation is complete, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after completing the installation. Once the Docker installation is complete, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after completing the installation.

@ -1 +1 @@
Subproject commit ac4181aea403d888e63cb527c700e80013c68ea8 Subproject commit 9174d8f8cb584744dd7a53f69d324f490ee82ee3

View file

@ -743,7 +743,7 @@ App::post('/v1/databases/:databaseId/collections')
])); ]));
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
$dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); $dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), permissions: $permissions ?? [], documentSecurity: $documentSecurity);
} catch (DuplicateException) { } catch (DuplicateException) {
throw new Exception(Exception::COLLECTION_ALREADY_EXISTS); throw new Exception(Exception::COLLECTION_ALREADY_EXISTS);
} catch (LimitException) { } catch (LimitException) {
@ -1001,6 +1001,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
->setAttribute('documentSecurity', $documentSecurity) ->setAttribute('documentSecurity', $documentSecurity)
->setAttribute('enabled', $enabled) ->setAttribute('enabled', $enabled)
->setAttribute('search', implode(' ', [$collectionId, $name]))); ->setAttribute('search', implode(' ', [$collectionId, $name])));
$dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity);
} catch (AuthorizationException) { } catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED); throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (StructureException $exception) { } catch (StructureException $exception) {
@ -2743,8 +2744,13 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
if (empty($related)) { if (empty($related)) {
continue; continue;
} }
if (!\is_array($related)) {
$related = [$related]; $isList = \is_array($related) && \array_values($related) === $related;
if ($isList) {
$relations = $related;
} else {
$relations = [$related];
} }
$relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollectionId = $relationship->getAttribute('relatedCollection');
@ -2752,7 +2758,15 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)
); );
foreach ($related as $relation) { foreach ($relations as &$relation) {
if (
\is_array($relation)
&& \array_values($relation) !== $relation
&& !isset($relation['$id'])
) {
$relation['$id'] = ID::unique();
$relation = new Document($relation);
}
if ($relation instanceof Document) { if ($relation instanceof Document) {
$current = Authorization::skip( $current = Authorization::skip(
fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()) fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId())
@ -2761,7 +2775,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
if ($current->isEmpty()) { if ($current->isEmpty()) {
$type = Database::PERMISSION_CREATE; $type = Database::PERMISSION_CREATE;
if (!isset($relation['$id']) || $relation['$id'] === 'unique()') { if (isset($relation['$id']) && $relation['$id'] === 'unique()') {
$relation['$id'] = ID::unique(); $relation['$id'] = ID::unique();
} }
} else { } else {
@ -2774,6 +2788,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
$checkPermissions($relatedCollection, $relation, $type); $checkPermissions($relatedCollection, $relation, $type);
} }
} }
if ($isList) {
$document->setAttribute($relationship->getAttribute('key'), \array_values($relations));
} else {
$document->setAttribute($relationship->getAttribute('key'), \reset($relations));
}
} }
}; };
@ -2866,12 +2886,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
$collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); $collection = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId));
if ($collection->isEmpty() || !$collection->getAttribute('enabled')) { if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) {
if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) { if (!$collection->getAttribute('documentSecurity', false)) {
throw new Exception(Exception::COLLECTION_NOT_FOUND); $validator = new Authorization(Database::PERMISSION_READ);
if (!$validator->isValid($collection->getRead())) {
$collection = new Document();
}
} }
} }
if ($collection->isEmpty() || !$collection->getAttribute('enabled')) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
// Validate queries // Validate queries
$queriesValidator = new Documents($collection->getAttribute('attributes'), $collection->getAttribute('indexes')); $queriesValidator = new Documents($collection->getAttribute('attributes'), $collection->getAttribute('indexes'));
$validQueries = $queriesValidator->isValid($queries); $validQueries = $queriesValidator->isValid($queries);
@ -2898,34 +2925,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
$filterQueries = Query::groupByType($queries)['filters']; $filterQueries = Query::groupByType($queries)['filters'];
$documents = Authorization::skip(fn () => $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries)); $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filterQueries, APP_LIMIT_COUNT);
$documentSecurity = $collection->getAttribute('documentSecurity', false);
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($collection->getRead());
if (!$valid) {
$total = $documentSecurity
? $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filterQueries, APP_LIMIT_COUNT)
: 0;
} else {
$total = Authorization::skip(fn() => $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filterQueries, APP_LIMIT_COUNT));
}
// Add $collectionId and $databaseId for all documents // Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool { $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool {
$documentSecurity = $collection->getAttribute('documentSecurity', false); if ($document->isEmpty()) {
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($collection->getRead());
if (!$documentSecurity && !$valid) {
return false;
}
$valid = $valid || $validator->isValid($document->getRead());
if ($documentSecurity && !$valid) {
return false; return false;
} }
$document->removeAttribute('$collection');
$document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId()); $document->setAttribute('$collectionId', $collection->getId());
@ -2969,18 +2978,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
}; };
// The linter is forcing this indentation // The linter is forcing this indentation
foreach ($documents as $index => $document) { foreach ($documents as $document) {
if (!$processDocument($collection, $document)) { $processDocument($collection, $document);
unset($documents[$index]);
if ($valid) {
$total--;
}
}
} }
$documents = \array_values($documents);
$response->dynamic(new Document([ $response->dynamic(new Document([
'total' => $total, 'total' => $total,
'documents' => $documents, 'documents' => $documents,
@ -3035,7 +3036,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
$queries = Query::parseQueries($queries); $queries = Query::parseQueries($queries);
$document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries)); $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries);
if ($document->isEmpty()) { if ($document->isEmpty()) {
throw new Exception(Exception::DOCUMENT_NOT_FOUND); throw new Exception(Exception::DOCUMENT_NOT_FOUND);
@ -3043,17 +3044,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
// Add $collectionId and $databaseId for all documents // 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) {
$documentSecurity = $collection->getAttribute('documentSecurity', false); if ($document->isEmpty()) {
$validator = new Authorization(Database::PERMISSION_READ); return;
$valid = $validator->isValid($collection->getRead());
if (!$documentSecurity && !$valid) {
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
}
$valid = $valid || $validator->isValid($document->getRead());
if ($documentSecurity && !$valid) {
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
} }
$document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$databaseId', $database->getId());
@ -3287,7 +3279,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
$permissions = $document->getPermissions() ?? []; $permissions = $document->getPermissions() ?? [];
} }
$data = \array_merge($document->getArrayCopy(), $data);
$data['$collection'] = $collection->getId(); // Make sure user doesn't switch collectionID $data['$collection'] = $collection->getId(); // Make sure user doesn't switch collectionID
$data['$createdAt'] = $document->getCreatedAt(); // Make sure user doesn't switch createdAt $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['$id'] = $document->getId(); // Make sure user doesn't switch document unique ID
@ -3321,8 +3312,13 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
if (empty($related)) { if (empty($related)) {
continue; continue;
} }
if (!\is_array($related)) {
$related = [$related]; $isList = \is_array($related) && \array_values($related) === $related;
if ($isList) {
$relations = $related;
} else {
$relations = [$related];
} }
$relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollectionId = $relationship->getAttribute('relatedCollection');
@ -3330,7 +3326,15 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) fn() => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)
); );
foreach ($related as $relation) { foreach ($relations as &$relation) {
if (
\is_array($relation)
&& \array_values($relation) !== $relation
&& !isset($relation['$id'])
) {
$relation['$id'] = ID::unique();
$relation = new Document($relation);
}
if ($relation instanceof Document) { if ($relation instanceof Document) {
$oldDocument = Authorization::skip(fn() => $dbForProject->getDocument( $oldDocument = Authorization::skip(fn() => $dbForProject->getDocument(
'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(),
@ -3340,7 +3344,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
if ($oldDocument->isEmpty()) { if ($oldDocument->isEmpty()) {
$type = Database::PERMISSION_CREATE; $type = Database::PERMISSION_CREATE;
if (!isset($relation['$id']) || $relation['$id'] === 'unique()') { if (isset($relation['$id']) && $relation['$id'] === 'unique()') {
$relation['$id'] = ID::unique(); $relation['$id'] = ID::unique();
} }
} else { } else {
@ -3353,20 +3357,28 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
$checkPermissions($relatedCollection, $relation, $oldDocument, $type); $checkPermissions($relatedCollection, $relation, $oldDocument, $type);
} }
} }
if ($isList) {
$document->setAttribute($relationship->getAttribute('key'), \array_values($relations));
} else {
$document->setAttribute($relationship->getAttribute('key'), \reset($relations));
}
} }
}; };
$checkPermissions($collection, $newDocument, $document, Database::PERMISSION_UPDATE); $checkPermissions($collection, $newDocument, $document, Database::PERMISSION_UPDATE);
$newDocument = new Document(\array_merge($document->getArrayCopy(), $data));
try { try {
$document = Authorization::skip(fn() => $dbForProject->withRequestTimestamp( $document = $dbForProject->withRequestTimestamp(
$requestTimestamp, $requestTimestamp,
fn () => $dbForProject->updateDocument( fn () => $dbForProject->updateDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$document->getId(), $document->getId(),
$newDocument $newDocument
) )
)); );
} catch (AuthorizationException) { } catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED); throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (DuplicateException) { } catch (DuplicateException) {

View file

@ -1237,7 +1237,7 @@ App::get('/v1/projects/:projectId/platforms')
} }
$platforms = $dbForConsole->find('platforms', [ $platforms = $dbForConsole->find('platforms', [
Query::equal('projectId', [$project->getId()]), Query::equal('projectInternalId', [$project->getInternalId()]),
Query::limit(5000), Query::limit(5000),
]); ]);

View file

@ -115,12 +115,6 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
if (!$dbForConsole->getCollection($key)->isEmpty()) { if (!$dbForConsole->getCollection($key)->isEmpty()) {
continue; continue;
} }
/**
* Skip to prevent 0.16 migration issues.
*/
if (in_array($key, ['cache', 'variables']) && $dbForConsole->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'), 'bucket_1')) {
continue;
}
Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...'); Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...');

View file

@ -101,7 +101,7 @@ const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return
const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
const APP_CACHE_BUSTER = 503; const APP_CACHE_BUSTER = 503;
const APP_VERSION_STABLE = '1.3.1'; const APP_VERSION_STABLE = '1.3.2';
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
const APP_DATABASE_ATTRIBUTE_IP = 'ip'; const APP_DATABASE_ATTRIBUTE_IP = 'ip';

View file

@ -95,9 +95,9 @@ $cli
if (is_null($value)) { if (is_null($value)) {
continue; continue;
} }
foreach ($vars as &$var) { foreach ($vars as $i => $var) {
if ($var['name'] === $key) { if ($var['name'] === $key) {
$var['default'] = $value; $vars[$i]['default'] = $value;
} }
} }
} }
@ -114,9 +114,9 @@ $cli
if (is_null($value)) { if (is_null($value)) {
continue; continue;
} }
foreach ($vars as &$var) { foreach ($vars as $i => $var) {
if ($var['name'] === $key) { if ($var['name'] === $key) {
$var['default'] = $value; $vars[$i]['default'] = $value;
} }
} }
} }
@ -146,7 +146,7 @@ $cli
$input = []; $input = [];
foreach ($vars as $key => $var) { foreach ($vars as $var) {
if (!empty($var['filter']) && ($interactive !== 'Y' || !Console::isInteractive())) { if (!empty($var['filter']) && ($interactive !== 'Y' || !Console::isInteractive())) {
if ($data && $var['default'] !== null) { if ($data && $var['default'] !== null) {
$input[$var['name']] = $var['default']; $input[$var['name']] = $var['default'];

View file

@ -9,7 +9,6 @@ use Utopia\Database\Document;
use Utopia\Database\Query; use Utopia\Database\Query;
use Appwrite\Resque\Worker; use Appwrite\Resque\Worker;
use Executor\Executor; use Executor\Executor;
use Utopia\Storage\Device\Local;
use Utopia\Abuse\Abuse; use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit; use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\CLI\Console; use Utopia\CLI\Console;
@ -291,12 +290,13 @@ class DeletesV1 extends Worker
protected function deleteProject(Document $document): void protected function deleteProject(Document $document): void
{ {
$projectId = $document->getId(); $projectId = $document->getId();
$projectInternalId = $document->getInternalId();
// Delete project domains and certificates // Delete project certificates
$dbForConsole = $this->getConsoleDB(); $dbForConsole = $this->getConsoleDB();
$domains = $dbForConsole->find('domains', [ $domains = $dbForConsole->find('domains', [
Query::equal('projectInternalId', [$document->getInternalId()]) Query::equal('projectInternalId', [$projectInternalId])
]); ]);
foreach ($domains as $domain) { foreach ($domains as $domain) {
@ -318,6 +318,26 @@ class DeletesV1 extends Worker
} }
} }
// Delete Platforms
$this->deleteByGroup('platforms', [
Query::equal('projectInternalId', [$projectInternalId])
], $dbForConsole);
// Delete Domains
$this->deleteByGroup('domains', [
Query::equal('projectInternalId', [$projectInternalId])
], $dbForConsole);
// Delete Keys
$this->deleteByGroup('keys', [
Query::equal('projectInternalId', [$projectInternalId])
], $dbForConsole);
// Delete Webhooks
$this->deleteByGroup('webhooks', [
Query::equal('projectInternalId', [$projectInternalId])
], $dbForConsole);
// Delete metadata tables // Delete metadata tables
try { try {
$dbForProject->deleteCollection('_metadata'); $dbForProject->deleteCollection('_metadata');

View file

@ -43,13 +43,13 @@
"ext-sockets": "*", "ext-sockets": "*",
"appwrite/php-clamav": "1.1.*", "appwrite/php-clamav": "1.1.*",
"appwrite/php-runtimes": "0.11.*", "appwrite/php-runtimes": "0.11.*",
"utopia-php/abuse": "0.24.*", "utopia-php/abuse": "0.25.*",
"utopia-php/analytics": "0.2.*", "utopia-php/analytics": "0.2.*",
"utopia-php/audit": "0.25.*", "utopia-php/audit": "0.26.*",
"utopia-php/cache": "0.8.*", "utopia-php/cache": "0.8.*",
"utopia-php/cli": "0.13.*", "utopia-php/cli": "0.13.*",
"utopia-php/config": "0.2.*", "utopia-php/config": "0.2.*",
"utopia-php/database": "0.35.*", "utopia-php/database": "0.36.*",
"utopia-php/domains": "1.1.*", "utopia-php/domains": "1.1.*",
"utopia-php/framework": "0.28.*", "utopia-php/framework": "0.28.*",
"utopia-php/image": "0.5.*", "utopia-php/image": "0.5.*",

117
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "87de4ea3130e576470a63b21628e30fb", "content-hash": "169ab6e7dd540e45309d3c5093506fad",
"packages": [ "packages": [
{ {
"name": "adhocore/jwt", "name": "adhocore/jwt",
@ -300,16 +300,16 @@
}, },
{ {
"name": "colinmollenhour/credis", "name": "colinmollenhour/credis",
"version": "v1.14.0", "version": "v1.15.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/colinmollenhour/credis.git", "url": "https://github.com/colinmollenhour/credis.git",
"reference": "dccc8a46586475075fbb012d8bd523b8a938c2dc" "reference": "28810439de1d9597b7ba11794ed9479fb6f3de7c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/colinmollenhour/credis/zipball/dccc8a46586475075fbb012d8bd523b8a938c2dc", "url": "https://api.github.com/repos/colinmollenhour/credis/zipball/28810439de1d9597b7ba11794ed9479fb6f3de7c",
"reference": "dccc8a46586475075fbb012d8bd523b8a938c2dc", "reference": "28810439de1d9597b7ba11794ed9479fb6f3de7c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -341,9 +341,9 @@
"homepage": "https://github.com/colinmollenhour/credis", "homepage": "https://github.com/colinmollenhour/credis",
"support": { "support": {
"issues": "https://github.com/colinmollenhour/credis/issues", "issues": "https://github.com/colinmollenhour/credis/issues",
"source": "https://github.com/colinmollenhour/credis/tree/v1.14.0" "source": "https://github.com/colinmollenhour/credis/tree/v1.15.0"
}, },
"time": "2022-11-09T01:18:39+00:00" "time": "2023-04-18T15:34:23+00:00"
}, },
{ {
"name": "composer/package-versions-deprecated", "name": "composer/package-versions-deprecated",
@ -481,22 +481,22 @@
}, },
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
"version": "7.5.0", "version": "7.5.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/guzzle.git", "url": "https://github.com/guzzle/guzzle.git",
"reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba" "reference": "b964ca597e86b752cd994f27293e9fa6b6a95ed9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/b50a2a1251152e43f6a37f0fa053e730a67d25ba", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b964ca597e86b752cd994f27293e9fa6b6a95ed9",
"reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba", "reference": "b964ca597e86b752cd994f27293e9fa6b6a95ed9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"guzzlehttp/promises": "^1.5", "guzzlehttp/promises": "^1.5",
"guzzlehttp/psr7": "^1.9 || ^2.4", "guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"php": "^7.2.5 || ^8.0", "php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0", "psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0" "symfony/deprecation-contracts": "^2.2 || ^3.0"
@ -589,7 +589,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/guzzle/guzzle/issues", "issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.5.0" "source": "https://github.com/guzzle/guzzle/tree/7.5.1"
}, },
"funding": [ "funding": [
{ {
@ -605,7 +605,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-08-28T15:39:27+00:00" "time": "2023-04-17T16:30:08+00:00"
}, },
{ {
"name": "guzzlehttp/promises", "name": "guzzlehttp/promises",
@ -693,22 +693,22 @@
}, },
{ {
"name": "guzzlehttp/psr7", "name": "guzzlehttp/psr7",
"version": "2.4.4", "version": "2.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/psr7.git", "url": "https://github.com/guzzle/psr7.git",
"reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf" "reference": "b635f279edd83fc275f822a1188157ffea568ff6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf", "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6",
"reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf", "reference": "b635f279edd83fc275f822a1188157ffea568ff6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.2.5 || ^8.0", "php": "^7.2.5 || ^8.0",
"psr/http-factory": "^1.0", "psr/http-factory": "^1.0",
"psr/http-message": "^1.0", "psr/http-message": "^1.1 || ^2.0",
"ralouphie/getallheaders": "^3.0" "ralouphie/getallheaders": "^3.0"
}, },
"provide": { "provide": {
@ -728,9 +728,6 @@
"bamarni-bin": { "bamarni-bin": {
"bin-links": true, "bin-links": true,
"forward-command": false "forward-command": false
},
"branch-alias": {
"dev-master": "2.4-dev"
} }
}, },
"autoload": { "autoload": {
@ -792,7 +789,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/guzzle/psr7/issues", "issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.4.4" "source": "https://github.com/guzzle/psr7/tree/2.5.0"
}, },
"funding": [ "funding": [
{ {
@ -808,7 +805,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-03-09T13:19:02+00:00" "time": "2023-04-17T16:11:26+00:00"
}, },
{ {
"name": "influxdb/influxdb-php", "name": "influxdb/influxdb-php",
@ -1372,16 +1369,16 @@
}, },
{ {
"name": "psr/http-message", "name": "psr/http-message",
"version": "1.1", "version": "2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/php-fig/http-message.git", "url": "https://github.com/php-fig/http-message.git",
"reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1390,7 +1387,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.1.x-dev" "dev-master": "2.0.x-dev"
} }
}, },
"autoload": { "autoload": {
@ -1405,7 +1402,7 @@
"authors": [ "authors": [
{ {
"name": "PHP-FIG", "name": "PHP-FIG",
"homepage": "http://www.php-fig.org/" "homepage": "https://www.php-fig.org/"
} }
], ],
"description": "Common interface for HTTP messages", "description": "Common interface for HTTP messages",
@ -1419,9 +1416,9 @@
"response" "response"
], ],
"support": { "support": {
"source": "https://github.com/php-fig/http-message/tree/1.1" "source": "https://github.com/php-fig/http-message/tree/2.0"
}, },
"time": "2023-04-04T09:50:52+00:00" "time": "2023-04-04T09:54:51+00:00"
}, },
{ {
"name": "psr/log", "name": "psr/log",
@ -1808,26 +1805,26 @@
}, },
{ {
"name": "utopia-php/abuse", "name": "utopia-php/abuse",
"version": "0.24.0", "version": "0.25.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/abuse.git", "url": "https://github.com/utopia-php/abuse.git",
"reference": "403641f16a53b81ac40b91111a86e5672da49e8c" "reference": "49a180cab5316cddec9676d900d5112d03e97ffc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/403641f16a53b81ac40b91111a86e5672da49e8c", "url": "https://api.github.com/repos/utopia-php/abuse/zipball/49a180cab5316cddec9676d900d5112d03e97ffc",
"reference": "403641f16a53b81ac40b91111a86e5672da49e8c", "reference": "49a180cab5316cddec9676d900d5112d03e97ffc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-curl": "*", "ext-curl": "*",
"ext-pdo": "*", "ext-pdo": "*",
"php": ">=8.0", "php": ">=8.0",
"utopia-php/database": "0.35.*" "utopia-php/database": "0.36.*"
}, },
"require-dev": { "require-dev": {
"laravel/pint": "1.2.*", "laravel/pint": "1.5.*",
"phpstan/phpstan": "^1.9", "phpstan/phpstan": "^1.9",
"phpunit/phpunit": "^9.4" "phpunit/phpunit": "^9.4"
}, },
@ -1851,9 +1848,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/abuse/issues", "issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.24.0" "source": "https://github.com/utopia-php/abuse/tree/0.25.0"
}, },
"time": "2023-04-11T05:31:55+00:00" "time": "2023-04-27T15:43:47+00:00"
}, },
{ {
"name": "utopia-php/analytics", "name": "utopia-php/analytics",
@ -1912,24 +1909,24 @@
}, },
{ {
"name": "utopia-php/audit", "name": "utopia-php/audit",
"version": "0.25.0", "version": "0.26.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/audit.git", "url": "https://github.com/utopia-php/audit.git",
"reference": "adc209f2e16878e5468f0b9cfd9f7f7ab497db31" "reference": "e7228080f14df28737fbb050c180c26d86ac0403"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/adc209f2e16878e5468f0b9cfd9f7f7ab497db31", "url": "https://api.github.com/repos/utopia-php/audit/zipball/e7228080f14df28737fbb050c180c26d86ac0403",
"reference": "adc209f2e16878e5468f0b9cfd9f7f7ab497db31", "reference": "e7228080f14df28737fbb050c180c26d86ac0403",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.0", "php": ">=8.0",
"utopia-php/database": "0.35.*" "utopia-php/database": "0.36.*"
}, },
"require-dev": { "require-dev": {
"laravel/pint": "1.2.*", "laravel/pint": "1.5.*",
"phpstan/phpstan": "^1.8", "phpstan/phpstan": "^1.8",
"phpunit/phpunit": "^9.3" "phpunit/phpunit": "^9.3"
}, },
@ -1953,9 +1950,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/audit/issues", "issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.25.0" "source": "https://github.com/utopia-php/audit/tree/0.26.0"
}, },
"time": "2023-04-11T05:31:15+00:00" "time": "2023-04-27T15:43:50+00:00"
}, },
{ {
"name": "utopia-php/cache", "name": "utopia-php/cache",
@ -2112,16 +2109,16 @@
}, },
{ {
"name": "utopia-php/database", "name": "utopia-php/database",
"version": "0.35.0", "version": "0.36.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/database.git", "url": "https://github.com/utopia-php/database.git",
"reference": "f162c142fd61753c4b413b15c3c4041f3cd00bb2" "reference": "f6ab65e59a199da5155c114564077b1ab8c4daef"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/f162c142fd61753c4b413b15c3c4041f3cd00bb2", "url": "https://api.github.com/repos/utopia-php/database/zipball/f6ab65e59a199da5155c114564077b1ab8c4daef",
"reference": "f162c142fd61753c4b413b15c3c4041f3cd00bb2", "reference": "f6ab65e59a199da5155c114564077b1ab8c4daef",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2164,9 +2161,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/database/issues", "issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.35.0" "source": "https://github.com/utopia-php/database/tree/0.36.1"
}, },
"time": "2023-04-11T04:02:22+00:00" "time": "2023-04-27T08:39:55+00:00"
}, },
{ {
"name": "utopia-php/domains", "name": "utopia-php/domains",
@ -3787,16 +3784,16 @@
}, },
{ {
"name": "phpstan/phpdoc-parser", "name": "phpstan/phpdoc-parser",
"version": "1.18.1", "version": "1.20.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git", "url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "22dcdfd725ddf99583bfe398fc624ad6c5004a0f" "reference": "6c04009f6cae6eda2f040745b6b846080ef069c2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/22dcdfd725ddf99583bfe398fc624ad6c5004a0f", "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6c04009f6cae6eda2f040745b6b846080ef069c2",
"reference": "22dcdfd725ddf99583bfe398fc624ad6c5004a0f", "reference": "6c04009f6cae6eda2f040745b6b846080ef069c2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3826,9 +3823,9 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types", "description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": { "support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues", "issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.18.1" "source": "https://github.com/phpstan/phpdoc-parser/tree/1.20.3"
}, },
"time": "2023-04-07T11:51:11+00:00" "time": "2023-04-25T09:01:03+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",

View file

@ -37,6 +37,9 @@ abstract class Migration
*/ */
protected Database $consoleDB; protected Database $consoleDB;
/**
* @var \PDO
*/
protected \PDO $pdo; protected \PDO $pdo;
/** /**
@ -54,6 +57,7 @@ abstract class Migration
'1.2.1' => 'V17', '1.2.1' => 'V17',
'1.3.0' => 'V18', '1.3.0' => 'V18',
'1.3.1' => 'V18', '1.3.1' => 'V18',
'1.3.2' => 'V18',
]; ];
/** /**
@ -102,6 +106,12 @@ abstract class Migration
return $this; return $this;
} }
/**
* Set PDO for Migration.
*
* @param \PDO $pdo
* @return \Appwrite\Migration\Migration
*/
public function setPDO(\PDO $pdo): self public function setPDO(\PDO $pdo): self
{ {
$this->pdo = $pdo; $this->pdo = $pdo;

View file

@ -6,6 +6,8 @@ use Appwrite\Migration\Migration;
use Utopia\CLI\Console; use Utopia\CLI\Console;
use Utopia\Database\Database; use Utopia\Database\Database;
use Utopia\Database\Document; use Utopia\Database\Document;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
class V18 extends Migration class V18 extends Migration
{ {
@ -25,6 +27,7 @@ class V18 extends Migration
Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')');
$this->projectDB->setNamespace("_{$this->project->getInternalId()}"); $this->projectDB->setNamespace("_{$this->project->getInternalId()}");
$this->addDocumentSecurityToProject();
Console::info('Migrating Databases'); Console::info('Migrating Databases');
$this->migrateDatabases(); $this->migrateDatabases();
@ -58,6 +61,15 @@ class V18 extends Migration
} }
$this->changeAttributeInternalType($collectionTable, $attribute['key'], 'DOUBLE'); $this->changeAttributeInternalType($collectionTable, $attribute['key'], 'DOUBLE');
} }
try {
$documentSecurity = $collection->getAttribute('documentSecurity', false);
$permissions = $collection->getPermissions();
$this->projectDB->updateCollection($collectionTable, $permissions, $documentSecurity);
} catch (\Throwable $th) {
Console::warning($th->getMessage());
}
} }
} }
} }
@ -81,6 +93,12 @@ class V18 extends Migration
$this->changeAttributeInternalType($id, $attribute['$id'], 'DOUBLE'); $this->changeAttributeInternalType($id, $attribute['$id'], 'DOUBLE');
} }
try {
$this->projectDB->updateCollection($id, [Permission::create(Role::any())], true);
} catch (\Throwable $th) {
Console::warning($th->getMessage());
}
switch ($id) { switch ($id) {
case 'users': case 'users':
try { try {
@ -168,4 +186,25 @@ class V18 extends Migration
return $document; return $document;
} }
protected function addDocumentSecurityToProject(): void
{
try {
/**
* Create 'documentSecurity' column
*/
$this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute();
} catch (\Throwable $th) {
Console::warning($th->getMessage());
}
try {
/**
* Set 'documentSecurity' column to 1 if NULL
*/
$this->pdo->prepare("UPDATE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute();
} catch (\Throwable $th) {
Console::warning($th->getMessage());
}
}
} }

View file

@ -4,6 +4,7 @@ namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response; use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response\Model;
use Utopia\Database\Document;
class Team extends Model class Team extends Model
{ {
@ -49,6 +50,24 @@ class Team extends Model
; ;
} }
/**
* Process Document before returning it to the client
*
* @return Document
*/
public function filter(Document $document): Document
{
$prefs = $document->getAttribute('prefs');
if ($prefs instanceof Document) {
$prefs = $prefs->getArrayCopy();
}
if (is_array($prefs) && empty($prefs)) {
$document->setAttribute('prefs', new \stdClass());
}
return $document;
}
/** /**
* Get Name * Get Name
* *

View file

@ -2853,9 +2853,7 @@ trait DatabasesBase
]); ]);
// Current user has no collection permissions and document permissions are disabled // Current user has no collection permissions and document permissions are disabled
$this->assertEquals(200, $documentsUser2['headers']['status-code']); $this->assertEquals(404, $documentsUser2['headers']['status-code']);
$this->assertEquals(0, $documentsUser2['body']['total']);
$this->assertEquals(true, empty($documentsUser2['body']['documents']));
// Enable document permissions // Enable document permissions
$collection = $this->client->call(CLient::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId, [ $collection = $this->client->call(CLient::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId, [
@ -3339,6 +3337,26 @@ trait DatabasesBase
$this->assertEquals('Library 1', $person1['body']['library']['libraryName']); $this->assertEquals('Library 1', $person1['body']['library']['libraryName']);
// Create without nested ID
$person2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => ID::unique(),
'data' => [
'library' => [
'libraryName' => 'Library 2',
],
],
'permissions' => [
Permission::read(Role::user($this->getUser()['$id'])),
Permission::update(Role::user($this->getUser()['$id'])),
Permission::delete(Role::user($this->getUser()['$id'])),
]
]);
$this->assertEquals('Library 2', $person2['body']['library']['libraryName']);
// Ensure IDs were set and internal IDs removed // Ensure IDs were set and internal IDs removed
$this->assertEquals($databaseId, $person1['body']['$databaseId']); $this->assertEquals($databaseId, $person1['body']['$databaseId']);
$this->assertEquals($databaseId, $person1['body']['library']['$databaseId']); $this->assertEquals($databaseId, $person1['body']['library']['$databaseId']);
@ -3901,7 +3919,7 @@ trait DatabasesBase
]); ]);
$this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(1, count($response['body']['documents'])); $this->assertEquals(2, count($response['body']['documents']));
$this->assertEquals(null, $response['body']['documents'][0]['fullName']); $this->assertEquals(null, $response['body']['documents'][0]['fullName']);
$this->assertArrayNotHasKey("libraries", $response['body']['documents'][0]); $this->assertArrayNotHasKey("libraries", $response['body']['documents'][0]);
} }

View file

@ -176,7 +176,7 @@ class DatabasesPermissionsTeamTest extends Scope
if ($success) { if ($success) {
$this->assertCount(1, $documents['body']['documents']); $this->assertCount(1, $documents['body']['documents']);
} else { } else {
$this->assertCount(0, $documents['body']['documents']); $this->assertEquals(404, $documents['headers']['status-code']);
} }
} }