From 92d6ed6089c34739fa672f0e081cdb0bf7f1ff47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 27 Apr 2022 12:44:47 +0000 Subject: [PATCH] Implement memberships subquery --- app/config/collections.php | 4 ++-- app/controllers/api/account.php | 8 +++---- app/controllers/api/teams.php | 39 +++++++-------------------------- app/controllers/api/users.php | 2 +- app/init.php | 12 ++++++++++ 5 files changed, 27 insertions(+), 38 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 3e3de4c7bd..dbff598476 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1077,8 +1077,8 @@ $collections = [ 'signed' => true, 'required' => false, 'default' => [], - 'array' => true, - 'filters' => ['json'], + 'array' => false, + 'filters' => ['subQueryMemberships'], ], [ '$id' => 'search', diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 200b845987..31bf7bf421 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -106,7 +106,7 @@ App::post('/v1/account') 'prefs' => new \stdClass(), 'sessions' => [], 'tokens' => [], - 'memberships' => [], + 'memberships' => null, 'search' => implode(' ', [$userId, $email, $name]), 'deleted' => false ]))); @@ -507,7 +507,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'prefs' => new \stdClass(), 'sessions' => [], 'tokens' => [], - 'memberships' => [], + 'memberships' => null, 'search' => implode(' ', [$userId, $email, $name]), 'deleted' => false ]))); @@ -681,7 +681,7 @@ App::post('/v1/account/sessions/magic-url') 'prefs' => new \stdClass(), 'sessions' => [], 'tokens' => [], - 'memberships' => [], + 'memberships' => null, 'search' => implode(' ', [$userId, $email]), 'deleted' => false ]))); @@ -953,7 +953,7 @@ App::post('/v1/account/sessions/anonymous') 'prefs' => new \stdClass(), 'sessions' => [], 'tokens' => [], - 'memberships' => [], + 'memberships' => null, 'search' => $userId, 'deleted' => false ]))); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 22705d3bf8..591bb82b1b 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -79,10 +79,7 @@ App::post('/v1/teams') ]); $membership = $dbForProject->createDocument('memberships', $membership); - - // Attach user to team - $user->setAttribute('memberships', $membership, Document::SET_TYPE_APPEND); - $user = $dbForProject->updateDocument('users', $user->getId(), $user); + $dbForProject->deleteCachedDocument('users', $user->getId()); } if (!empty($user->getId())) { @@ -340,7 +337,7 @@ App::post('/v1/teams/:teamId/memberships') 'prefs' => new \stdClass(), 'sessions' => [], 'tokens' => [], - 'memberships' => [], + 'memberships' => null, 'search' => implode(' ', [$userId, $email, $name]), ]))); } catch (Duplicate $th) { @@ -380,10 +377,7 @@ App::post('/v1/teams/:teamId/memberships') $team->setAttribute('total', $team->getAttribute('total', 0) + 1); $team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team)); - // Attach user to team - $invitee->setAttribute('memberships', $membership, Document::SET_TYPE_APPEND); - - $invitee = Authorization::skip(fn() => $dbForProject->updateDocument('users', $invitee->getId(), $invitee)); + $dbForProject->deleteCachedDocument('users', $invitee->getId()); } else { try { $membership = $dbForProject->createDocument('memberships', $membership); @@ -604,13 +598,8 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') /** * Replace membership on profile */ - $memberships = array_filter($profile->getAttribute('memberships'), fn (Document $m) => $m->getId() !== $membership->getId()); - - $profile - ->setAttribute('memberships', $memberships) - ->setAttribute('memberships', $membership, Document::SET_TYPE_APPEND); - - Authorization::skip(fn () => $dbForProject->updateDocument('users', $profile->getId(), $profile)); + + $dbForProject->deleteCachedDocument('users', $profile->getId()); $audits ->setParam('userId', $user->getId()) @@ -700,7 +689,6 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $user ->setAttribute('emailVerification', true) - ->setAttribute('memberships', $membership, Document::SET_TYPE_APPEND) ; // Log user in @@ -734,6 +722,8 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $user = $dbForProject->updateDocument('users', $user->getId(), $user); $membership = $dbForProject->updateDocument('memberships', $membership->getId(), $membership); + + $dbForProject->deleteCachedDocument('users', $user->getId()); $team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team->setAttribute('total', $team->getAttribute('total', 0) + 1))); @@ -813,20 +803,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') throw new Exception('Failed to remove membership from DB', 500, Exception::GENERAL_SERVER_ERROR); } - $memberships = $user->getAttribute('memberships', []); - - foreach ($memberships as $key => $child) { - /** @var Document $child */ - - if ($membershipId == $child->getId()) { - unset($memberships[$key]); - break; - } - } - - $user->setAttribute('memberships', $memberships); - - Authorization::skip(fn() => $dbForProject->updateDocument('users', $user->getId(), $user)); + $dbForProject->deleteCachedDocument('users', $user->getId()); if ($membership->getAttribute('confirm')) { // Count only confirmed members $team->setAttribute('total', \max($team->getAttribute('total', 0) - 1, 0)); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 6bb14c5003..bfb7d4d17a 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -65,7 +65,7 @@ App::post('/v1/users') 'prefs' => new \stdClass(), 'sessions' => [], 'tokens' => [], - 'memberships' => [], + 'memberships' => null, 'search' => implode(' ', [$userId, $email, $name]), 'deleted' => false ])); diff --git a/app/init.php b/app/init.php index fd509297f6..cac7a9701b 100644 --- a/app/init.php +++ b/app/init.php @@ -301,6 +301,18 @@ Database::addFilter('subQueryWebhooks', } ); +Database::addFilter('subQueryMemberships', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + return Authorization::skip(fn() => $database + ->find('memberships', [ + new Query('userId', Query::TYPE_EQUAL, [$document->getId()]) + ], $database->getIndexLimit(), 0, [])); + } +); + Database::addFilter('encrypt', function($value) { $key = App::getEnv('_APP_OPENSSL_KEY_V1');