From fce230dca8b998f3810d051f3a878aa4761d1711 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 17 Jul 2023 16:42:46 -0700 Subject: [PATCH 1/2] Fix team delete Ensure all memberships are deleted and the cached users are invalidated so that the nested memberships will refresh. --- app/controllers/api/teams.php | 12 ------------ app/workers/deletes.php | 18 +++++++++++++----- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 572b6f02a8..664e9a658b 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -255,18 +255,6 @@ App::delete('/v1/teams/:teamId') throw new Exception(Exception::TEAM_NOT_FOUND); } - $memberships = $dbForProject->find('memberships', [ - Query::equal('teamId', [$teamId]), - Query::limit(2000), // TODO fix members limit - ]); - - // TODO delete all members individually from the user object - foreach ($memberships as $membership) { - if (!$dbForProject->deleteDocument('memberships', $membership->getId())) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove membership for team from DB'); - } - } - if (!$dbForProject->deleteDocument('teams', $teamId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove team from DB'); } diff --git a/app/workers/deletes.php b/app/workers/deletes.php index 6eed3a8a40..840e77f9f8 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -8,7 +8,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; use Appwrite\Resque\Worker; -use Executor\Executor; use Utopia\Storage\Device\Local; use Utopia\Abuse\Abuse; use Utopia\Abuse\Adapters\TimeLimit; @@ -296,12 +295,21 @@ class DeletesV1 extends Worker */ protected function deleteMemberships(Document $document, Document $project): void { - $teamId = $document->getAttribute('teamId', ''); + $dbForProject = $this->getProjectDB($project); + $teamInternalId = $document->getInternalId(); // Delete Memberships - $this->deleteByGroup('memberships', [ - Query::equal('teamId', [$teamId]) - ], $this->getProjectDB($project)); + $this->deleteByGroup( + 'memberships', + [ + Query::equal('teamInternalId', [$teamInternalId]) + ], + $dbForProject, + function (Document $membership) use ($dbForProject) { + $userId = $membership->getAttribute('userId'); + $dbForProject->deleteCachedDocument('users', $userId); + } + ); } /** From 308c92f203c329d38e67db79204b6ecfcc87a45d Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 17 Jul 2023 17:07:37 -0700 Subject: [PATCH 2/2] Ensure resources are deleted using their internal Id This is necessary because a resource can be re-created with the same id. If we don't use the internal id, the newer recreated resource can be deleted. --- app/workers/deletes.php | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/app/workers/deletes.php b/app/workers/deletes.php index 840e77f9f8..6b2522812f 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -254,6 +254,7 @@ class DeletesV1 extends Worker protected function deleteCollection(Document $document, Document $project): void { $collectionId = $document->getId(); + $collectionInternalId = $document->getInternalId(); $databaseId = $document->getAttribute('databaseId'); $databaseInternalId = $document->getAttribute('databaseInternalId'); @@ -262,13 +263,13 @@ class DeletesV1 extends Worker $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $document->getInternalId()); $this->deleteByGroup('attributes', [ - Query::equal('databaseId', [$databaseId]), - Query::equal('collectionId', [$collectionId]) + Query::equal('databaseInternalId', [$databaseInternalId]), + Query::equal('collectionInternalId', [$collectionInternalId]) ], $dbForProject); $this->deleteByGroup('indexes', [ - Query::equal('databaseId', [$databaseId]), - Query::equal('collectionId', [$collectionId]) + Query::equal('databaseInternalId', [$databaseInternalId]), + Query::equal('collectionInternalId', [$collectionInternalId]) ], $dbForProject); $this->deleteAuditLogsByResource('database/' . $databaseId . '/collection/' . $collectionId, $project); @@ -337,19 +338,20 @@ class DeletesV1 extends Worker protected function deleteUser(Document $document, Document $project): void { $userId = $document->getId(); + $userInternalId = $document->getInternalId(); $dbForProject = $this->getProjectDB($project); // Delete all sessions of this user from the sessions table and update the sessions field of the user record $this->deleteByGroup('sessions', [ - Query::equal('userId', [$userId]) + Query::equal('userInternalId', [$userInternalId]) ], $dbForProject); $dbForProject->deleteCachedDocument('users', $userId); // Delete Memberships and decrement team membership counts $this->deleteByGroup('memberships', [ - Query::equal('userId', [$userId]) + Query::equal('userInternalId', [$userInternalId]) ], $dbForProject, function (Document $document) use ($dbForProject) { if ($document->getAttribute('confirm')) { // Count only confirmed members $teamId = $document->getAttribute('teamId'); @@ -359,7 +361,7 @@ class DeletesV1 extends Worker 'teams', $teamId, // Ensure that total >= 0 - $team->setAttribute('total', \max($team->getAttribute('total', 0) - 1, 0)) + $team->setAttribute('total', \max($team->getAttribute('total', 0) - 1, 0)) ); } } @@ -367,7 +369,7 @@ class DeletesV1 extends Worker // Delete tokens $this->deleteByGroup('tokens', [ - Query::equal('userId', [$userId]) + Query::equal('userInternalId', [$userInternalId]) ], $dbForProject); } @@ -482,13 +484,14 @@ class DeletesV1 extends Worker $projectId = $project->getId(); $dbForProject = $this->getProjectDB($project); $functionId = $document->getId(); + $functionInternalId = $document->getInternalId(); /** * Delete Variables */ Console::info("Deleting variables for function " . $functionId); $this->deleteByGroup('variables', [ - Query::equal('functionId', [$functionId]) + Query::equal('functionInternalId', [$functionInternalId]) ], $dbForProject); /**