From 04afeb4a8d0004e8d8cb5e95ece1f9fbe218f2b8 Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 16 Nov 2023 15:56:52 +0200 Subject: [PATCH 1/7] tests --- app/controllers/api/databases.php | 47 ++++++ .../Databases/DatabasesCustomClientTest.php | 159 ++++++++++++++++++ 2 files changed, 206 insertions(+) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index f47e3f8265..a9eafb7976 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1640,8 +1640,55 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati Event $queueForEvents ) { $key ??= $relatedCollectionId; + $twoWayKeyNull = is_null($twoWayKey); $twoWayKey ??= $collectionId; + $databaseDocument = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + + if ($databaseDocument->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collectionDocument = $dbForProject->getDocument('database_' . $databaseDocument->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $databaseDocument->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + + if ($collection->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $relatedCollectionDocument = $dbForProject->getDocument('database_' . $databaseDocument->getInternalId(), $relatedCollectionId); + $relatedCollection = $dbForProject->getCollection('database_' . $databaseDocument->getInternalId() . '_collection_' . $relatedCollectionDocument->getInternalId()); + + if ($relatedCollection->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $attributes = $collection->getAttribute('attributes', []); + /** @var Document[] $attributes */ + foreach ($attributes as $attribute) { + if (\strtolower($attribute->getId()) === \strtolower($key)) { + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); + } + + if ( + $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP && + \strtolower($attribute->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) && + $attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId() + ) { + // Currently, we always throw an Exception even when, We do not want to change $twoWayKsy on $twoWayKeyNull + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); + } + + if ( + $type === Database::RELATION_MANY_TO_MANY && + $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP && + $attribute->getAttribute('options')['relationType'] === Database::RELATION_MANY_TO_MANY && + $attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId() + ) { + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Creating more than one "manyToMany" relationship on the same collection is currently not permitted.'); + } + } + $attribute = createAttribute( $databaseId, $collectionId, diff --git a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php index 743df9e53a..f3ab38be45 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php @@ -6,6 +6,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; +use Utopia\Database\Database; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -317,6 +318,164 @@ class DatabasesCustomClientTest extends Scope $this->assertEquals('restrict', $collection1RelationAttribute['onDelete']); } + public function testRelationshipSameTwoWayKey(): void + { + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Same two way key' + ]); + + $databaseId = $database['body']['$id']; + + $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'c1', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'c2', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + \sleep(2); + + $relation = $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' => Database::RELATION_ONE_TO_ONE, + 'twoWay' => false, + 'onDelete' => 'cascade', + 'key' => 'attr1', + 'twoWayKey' => 'same_key' + ]); + + \sleep(2); + + $this->assertEquals(202, $relation['headers']['status-code']); + $this->assertEquals('same_key', $relation['body']['twoWayKey']); + + $relation = $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' => Database::RELATION_ONE_TO_MANY, + 'twoWay' => false, + 'onDelete' => 'cascade', + 'key' => 'attr2', + 'twoWayKey' => 'same_key' + ]); + + \sleep(2); + + $this->assertEquals(409, $relation['body']['code']); + $this->assertEquals('Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.', $relation['body']['message']); + + // twoWayKey is null TwoWayKey is default + $relation = $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' => Database::RELATION_ONE_TO_MANY, + 'twoWay' => false, + 'onDelete' => 'cascade', + 'key' => 'attr3', + ]); + + \sleep(2); + + $this->assertEquals(202, $relation['headers']['status-code']); + $this->assertArrayHasKey('twoWayKey', $relation['body']); + + // twoWayKey is null, TwoWayKey is default, second POST + $relation = $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' => Database::RELATION_ONE_TO_MANY, + 'twoWay' => false, + 'onDelete' => 'cascade', + 'key' => 'attr4', + ]); + + \sleep(2); + + $this->assertEquals('Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.', $relation['body']['message']); + $this->assertEquals(409, $relation['body']['code']); + + // RelationshipManyToMany + $relation = $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' => Database::RELATION_MANY_TO_MANY, + 'twoWay' => true, + 'onDelete' => 'setNull', + 'key' => 'songs', + 'twoWayKey' => 'playlist', + ]); + + \sleep(2); + + $this->assertEquals(202, $relation['headers']['status-code']); + $this->assertArrayHasKey('twoWayKey', $relation['body']); + + // Second RelationshipManyToMany on Same collections + $relation = $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' => Database::RELATION_MANY_TO_MANY, + 'twoWay' => true, + 'onDelete' => 'setNull', + 'key' => 'songs2', + 'twoWayKey' => 'playlist2', + ]); + + \sleep(2); + + $this->assertEquals(409, $relation['body']['code']); + $this->assertEquals('Creating more than one "manyToMany" relationship on the same collection is currently not permitted.', $relation['body']['message']); + } + public function testUpdateWithoutRelationPermission(): void { $userId = $this->getUser()['$id']; From 99fed365dbc4ff2f6fc37707007b717f364d9a8c Mon Sep 17 00:00:00 2001 From: fogelito Date: Tue, 13 Feb 2024 12:05:47 +0200 Subject: [PATCH 2/7] Update comment --- app/controllers/api/databases.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index f0acd88e4b..63ac2e1f5d 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1614,7 +1614,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati Event $queueForEvents ) { $key ??= $relatedCollectionId; - $twoWayKeyNull = is_null($twoWayKey); $twoWayKey ??= $collectionId; $databaseDocument = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); @@ -1649,8 +1648,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati \strtolower($attribute->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) && $attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId() ) { - // Currently, we always throw an Exception even when, We do not want to change $twoWayKsy on $twoWayKeyNull - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); + // Console should provider a unique twoWayKey input! + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'TwoWayKey already exist in related collection'); } if ( From b9000e6d2f843d97deb973fc0f8c67d6b79286f8 Mon Sep 17 00:00:00 2001 From: fogelito Date: Tue, 13 Feb 2024 12:29:36 +0200 Subject: [PATCH 3/7] Changes message like Utopia --- app/controllers/api/databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 63ac2e1f5d..13fa9dca33 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1649,7 +1649,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati $attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId() ) { // Console should provider a unique twoWayKey input! - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'TwoWayKey already exist in related collection'); + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.'); } if ( From 172d7cbb02c6f7f3905d721101643a2a03a438d0 Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 21 Feb 2024 11:34:15 +0200 Subject: [PATCH 4/7] composer.lock --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index d67fc77aea..ba1caf51f0 100644 --- a/composer.lock +++ b/composer.lock @@ -2768,16 +2768,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.36.2", + "version": "0.36.3", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "0aa67479d75f0e0cb7b60454031534d7f0abaece" + "reference": "8d308f7f492545da3e51ea5b91c0778392c40b93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/0aa67479d75f0e0cb7b60454031534d7f0abaece", - "reference": "0aa67479d75f0e0cb7b60454031534d7f0abaece", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/8d308f7f492545da3e51ea5b91c0778392c40b93", + "reference": "8d308f7f492545da3e51ea5b91c0778392c40b93", "shasum": "" }, "require": { @@ -2813,9 +2813,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.36.2" + "source": "https://github.com/appwrite/sdk-generator/tree/0.36.3" }, - "time": "2024-01-19T01:04:35+00:00" + "time": "2024-02-14T06:33:38+00:00" }, { "name": "doctrine/deprecations", From af34f195c675fba5f935b7d33e2dd9dadcd5b06e Mon Sep 17 00:00:00 2001 From: fogelito Date: Sun, 25 Feb 2024 10:26:02 +0200 Subject: [PATCH 5/7] Address comments --- app/controllers/api/databases.php | 20 +++---- composer.lock | 86 +++++++++++++++---------------- 2 files changed, 54 insertions(+), 52 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 13fa9dca33..2e11630e05 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1616,21 +1616,21 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati $key ??= $relatedCollectionId; $twoWayKey ??= $collectionId; - $databaseDocument = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - if ($databaseDocument->isEmpty()) { + if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collectionDocument = $dbForProject->getDocument('database_' . $databaseDocument->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $databaseDocument->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $relatedCollectionDocument = $dbForProject->getDocument('database_' . $databaseDocument->getInternalId(), $relatedCollectionId); - $relatedCollection = $dbForProject->getCollection('database_' . $databaseDocument->getInternalId() . '_collection_' . $relatedCollectionDocument->getInternalId()); + $relatedCollectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); + $relatedCollection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollectionDocument->getInternalId()); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1639,22 +1639,24 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati $attributes = $collection->getAttribute('attributes', []); /** @var Document[] $attributes */ foreach ($attributes as $attribute) { + if ($attribute->getAttribute('type') !== Database::VAR_RELATIONSHIP) { + continue; + } + if (\strtolower($attribute->getId()) === \strtolower($key)) { throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); } if ( - $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP && \strtolower($attribute->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) && $attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId() ) { - // Console should provider a unique twoWayKey input! + // Console should provide a unique twoWayKey input! throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.'); } if ( $type === Database::RELATION_MANY_TO_MANY && - $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP && $attribute->getAttribute('options')['relationType'] === Database::RELATION_MANY_TO_MANY && $attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId() ) { diff --git a/composer.lock b/composer.lock index ba1caf51f0..74f898a15c 100644 --- a/composer.lock +++ b/composer.lock @@ -1540,16 +1540,16 @@ }, { "name": "utopia-php/database", - "version": "0.48.2", + "version": "0.48.4", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "0a231a2874fdbc0cf2ae2170b3f132fdee0ddfd4" + "reference": "02f20bd901b8fab26d7dc2c58f7da1d6a08d21c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/0a231a2874fdbc0cf2ae2170b3f132fdee0ddfd4", - "reference": "0a231a2874fdbc0cf2ae2170b3f132fdee0ddfd4", + "url": "https://api.github.com/repos/utopia-php/database/zipball/02f20bd901b8fab26d7dc2c58f7da1d6a08d21c0", + "reference": "02f20bd901b8fab26d7dc2c58f7da1d6a08d21c0", "shasum": "" }, "require": { @@ -1557,7 +1557,7 @@ "ext-pdo": "*", "php": ">=8.0", "utopia-php/cache": "0.9.*", - "utopia-php/framework": "0.*.*", + "utopia-php/framework": "0.33.*", "utopia-php/mongo": "0.3.*" }, "require-dev": { @@ -1590,9 +1590,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.48.2" + "source": "https://github.com/utopia-php/database/tree/0.48.4" }, - "time": "2024-02-02T14:10:14+00:00" + "time": "2024-02-23T03:22:55+00:00" }, { "name": "utopia-php/domains", @@ -1900,16 +1900,16 @@ }, { "name": "utopia-php/messaging", - "version": "0.9.0", + "version": "0.9.1", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "df54ba51570e886724590edeb03dbd455bb0464d" + "reference": "7beec07684e9e1dfcf4ab5b1ba731fa396dccbdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/df54ba51570e886724590edeb03dbd455bb0464d", - "reference": "df54ba51570e886724590edeb03dbd455bb0464d", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/7beec07684e9e1dfcf4ab5b1ba731fa396dccbdf", + "reference": "7beec07684e9e1dfcf4ab5b1ba731fa396dccbdf", "shasum": "" }, "require": { @@ -1944,9 +1944,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.9.0" + "source": "https://github.com/utopia-php/messaging/tree/0.9.1" }, - "time": "2024-01-31T11:51:27+00:00" + "time": "2024-02-15T03:44:44+00:00" }, { "name": "utopia-php/migration", @@ -2768,16 +2768,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.36.3", + "version": "0.36.4", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "8d308f7f492545da3e51ea5b91c0778392c40b93" + "reference": "8d932098009d62d37dda73cfe4ebc11f83e21405" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/8d308f7f492545da3e51ea5b91c0778392c40b93", - "reference": "8d308f7f492545da3e51ea5b91c0778392c40b93", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/8d932098009d62d37dda73cfe4ebc11f83e21405", + "reference": "8d932098009d62d37dda73cfe4ebc11f83e21405", "shasum": "" }, "require": { @@ -2813,9 +2813,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.36.3" + "source": "https://github.com/appwrite/sdk-generator/tree/0.36.4" }, - "time": "2024-02-14T06:33:38+00:00" + "time": "2024-02-20T16:36:15+00:00" }, { "name": "doctrine/deprecations", @@ -3119,16 +3119,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.0.0", + "version": "v5.0.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc" + "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4a21235f7e56e713259a6f76bf4b5ea08502b9dc", - "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2218c2252c874a4624ab2f613d86ac32d227bc69", + "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69", "shasum": "" }, "require": { @@ -3171,9 +3171,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.1" }, - "time": "2024-01-07T17:17:35+00:00" + "time": "2024-02-21T19:24:10+00:00" }, { "name": "phar-io/manifest", @@ -3398,21 +3398,21 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.8.0", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "fad452781b3d774e3337b0c0b245dd8e5a4455fc" + "reference": "153ae662783729388a584b4361f2545e4d841e3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fad452781b3d774e3337b0c0b245dd8e5a4455fc", - "reference": "fad452781b3d774e3337b0c0b245dd8e5a4455fc", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", "shasum": "" }, "require": { "doctrine/deprecations": "^1.0", - "php": "^7.4 || ^8.0", + "php": "^7.3 || ^8.0", "phpdocumentor/reflection-common": "^2.0", "phpstan/phpdoc-parser": "^1.13" }, @@ -3450,9 +3450,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.8.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" }, - "time": "2024-01-11T11:49:22+00:00" + "time": "2024-02-23T11:10:43+00:00" }, { "name": "phpspec/prophecy", @@ -3525,16 +3525,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.25.0", + "version": "1.26.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240" + "reference": "231e3186624c03d7e7c890ec662b81e6b0405227" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bd84b629c8de41aa2ae82c067c955e06f1b00240", - "reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/231e3186624c03d7e7c890ec662b81e6b0405227", + "reference": "231e3186624c03d7e7c890ec662b81e6b0405227", "shasum": "" }, "require": { @@ -3566,9 +3566,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.25.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.26.0" }, - "time": "2024-01-04T17:06:16+00:00" + "time": "2024-02-23T16:05:55+00:00" }, { "name": "phpunit/php-code-coverage", @@ -5008,16 +5008,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.8.1", + "version": "3.9.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "14f5fff1e64118595db5408e946f3a22c75807f7" + "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/14f5fff1e64118595db5408e946f3a22c75807f7", - "reference": "14f5fff1e64118595db5408e946f3a22c75807f7", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/d63cee4890a8afaf86a22e51ad4d97c91dd4579b", + "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b", "shasum": "" }, "require": { @@ -5084,7 +5084,7 @@ "type": "open_collective" } ], - "time": "2024-01-11T20:47:48+00:00" + "time": "2024-02-16T15:06:51+00:00" }, { "name": "swoole/ide-helper", From 1474bd65b0405bc0a1ac1ab2a708270475a7ffed Mon Sep 17 00:00:00 2001 From: fogelito Date: Sun, 25 Feb 2024 10:57:41 +0200 Subject: [PATCH 6/7] Rename $collectionDocument --- app/controllers/api/databases.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 2e11630e05..fdb986b155 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1622,8 +1622,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); From 3963b65f68da206766752f007f4cf3f873409fbf Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Sun, 25 Feb 2024 11:21:56 +0100 Subject: [PATCH 7/7] fix: mfa delete --- app/controllers/api/users.php | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 987c146e0d..3edecc23c3 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -1599,30 +1599,20 @@ App::delete('/v1/users/:userId/mfa/:type') ->label('sdk.response.model', Response::MODEL_USER) ->param('userId', '', new UID(), 'User ID.') ->param('type', null, new WhiteList(['totp']), 'Type of authenticator.') - ->param('otp', '', new Text(256), 'Valid verification token.') ->inject('requestTimestamp') ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $userId, string $type, string $otp, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $userId, string $type, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents) { $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); } - $success = match ($type) { - 'totp' => Challenge\TOTP::verify($user, $otp), - default => false - }; - - if (!$success) { - throw new Exception(Exception::USER_INVALID_TOKEN); - } - - if (!$user->getAttribute('totp')) { - throw new Exception(Exception::GENERAL_UNKNOWN, 'TOTP not added.'); - } + if (!$user->getAttribute('totp')) { + throw new Exception(Exception::GENERAL_UNKNOWN, 'TOTP not added.'); + } $user ->setAttribute('totp', false)