diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index a4de380561..4459322baf 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -327,22 +327,22 @@ function updateAttribute( } if ($type === Database::VAR_RELATIONSHIP) { - $options = \array_merge($attribute->getAttribute('options', []), $options); - $attribute->setAttribute('options', $options); + $primaryDocumentOptions = \array_merge($attribute->getAttribute('options', []), $options); + $attribute->setAttribute('options', $primaryDocumentOptions); $dbForProject->updateRelationship( collection: $collectionId, id: $key, - onDelete: $options['onDelete'], + onDelete: $primaryDocumentOptions['onDelete'], ); - if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection']); - $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + if ($primaryDocumentOptions['twoWay']) { + $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $primaryDocumentOptions['relatedCollection']); + + $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey']); $relatedOptions = \array_merge($relatedAttribute->getAttribute('options'), $options); $relatedAttribute->setAttribute('options', $relatedOptions); - - $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey'], $relatedAttribute); + $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); $dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); } } else { @@ -2623,7 +2623,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create') ->label('scope', 'documents.write') ->label('audits.event', 'document.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{response.$id}') ->label('usage.metric', 'documents.{scope}.requests.create') ->label('usage.params', ['databaseId:{request.databaseId}', 'collectionId:{request.collectionId}']) ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 0baff3726a..90aefbf809 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -684,17 +684,11 @@ App::delete('/v1/projects/:projectId') ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) ->label('sdk.response.model', Response::MODEL_NONE) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('password', '', new Password(), 'Your user password for confirmation. Must be at least 8 chars.') ->inject('response') ->inject('user') ->inject('dbForConsole') ->inject('deletes') - ->action(function (string $projectId, string $password, Response $response, Document $user, Database $dbForConsole, Delete $deletes) { - - if (!Auth::passwordVerify($password, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions'))) { // Double check user password - throw new Exception(Exception::USER_INVALID_CREDENTIALS); - } - + ->action(function (string $projectId, Response $response, Document $user, Database $dbForConsole, Delete $deletes) { $project = $dbForConsole->getDocument('projects', $projectId); if ($project->isEmpty()) { diff --git a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php index de59723e53..b0ab884a07 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php @@ -225,4 +225,95 @@ class DatabasesCustomClientTest extends Scope return []; } + + public function testUpdateTwoWayRelationship(): 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' => 'Test Database' + ]); + + $databaseId = $database['body']['$id']; + + + // Creating collection 1 + $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'level1', + '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'])), + ] + ]); + + // Creating collection 2 + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'level2', + '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); + + // Creating two way relationship between collection 1 and collection 2 from collection 1 + $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' => 'oneToMany', + 'twoWay' => true, + 'onDelete' => 'cascade', + 'key' => $collection2['body']['$id'], + 'twoWayKey' => $collection1['body']['$id'] + ]); + + \sleep(3); + + // Update relation from collection 2 to on delete restrict + $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/attributes/' . $collection1['body']['$id'] . '/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'onDelete' => 'restrict', + ]); + + // Fetching attributes after updating relation to compare + $collection1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; + + $this->assertEquals($relation['body']['side'], $collection1RelationAttribute['side']); + $this->assertEquals($relation['body']['twoWayKey'], $collection1RelationAttribute['twoWayKey']); + $this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']); + $this->assertEquals('restrict', $collection1RelationAttribute['onDelete']); + } } diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index b104b49904..c09bd262e3 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -3012,15 +3012,13 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $project['headers']['status-code']); - // Delete team - $team = $this->client->call(Client::METHOD_DELETE, '/projects/' . $projectId, array_merge([ + // Delete Project + $project = $this->client->call(Client::METHOD_DELETE, '/projects/' . $projectId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'password' => 'password' - ]); + ], $this->getHeaders())); - $this->assertEquals(204, $team['headers']['status-code']); + $this->assertEquals(204, $project['headers']['status-code']); // Ensure I can get team but not a project $team = $this->client->call(Client::METHOD_GET, '/teams/' . $teamId, array_merge([