diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 2b2e17b6a9..0b69ae26df 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -69,6 +69,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence()) || empty($document->getAttribute('databaseInternalId'))) { + return []; + } + $attributes = $database->getAuthorization()->skip(fn () => $database->find('attributes', [ Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), @@ -104,6 +108,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence()) || empty($document->getAttribute('databaseInternalId'))) { + return []; + } + return $database->getAuthorization()->skip(fn () => $database ->find('indexes', [ Query::equal('collectionInternalId', [$document->getSequence()]), @@ -119,6 +127,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + return $database->getAuthorization()->skip(fn () => $database ->find('platforms', [ Query::equal('projectInternalId', [$document->getSequence()]), @@ -133,6 +145,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + return $database->getAuthorization()->skip(fn () => $database ->find('keys', [ Query::equal('resourceType', ['projects']), @@ -148,6 +164,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + return $database->getAuthorization()->skip(fn () => $database ->find('devKeys', [ Query::equal('projectInternalId', [$document->getSequence()]), @@ -162,6 +182,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + return $database->getAuthorization()->skip(fn () => $database ->find('webhooks', [ Query::equal('projectInternalId', [$document->getSequence()]), @@ -176,6 +200,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + return $database->getAuthorization()->skip(fn () => $database->find('sessions', [ Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), @@ -189,6 +217,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + return $database->getAuthorization()->skip(fn () => $database ->find('tokens', [ Query::equal('userInternalId', [$document->getSequence()]), @@ -203,6 +235,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + return $database->getAuthorization()->skip(fn () => $database ->find('challenges', [ Query::equal('userInternalId', [$document->getSequence()]), @@ -217,6 +253,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + return $database->getAuthorization()->skip(fn () => $database ->find('authenticators', [ Query::equal('userInternalId', [$document->getSequence()]), @@ -231,6 +271,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + return $database->getAuthorization()->skip(fn () => $database ->find('memberships', [ Query::equal('userInternalId', [$document->getSequence()]), @@ -245,6 +289,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + $resourceType = match ($document->getCollection()) { 'functions' => ['function'], 'sites' => ['site'], @@ -331,6 +379,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + return $database->getAuthorization()->skip(fn () => $database ->find('targets', [ Query::equal('userInternalId', [$document->getSequence()]), @@ -345,6 +397,10 @@ Database::addFilter( return; }, function (mixed $value, Document $document, Database $database) { + if (empty($document->getSequence())) { + return []; + } + $targetIds = $database->getAuthorization()->skip(fn () => \array_map( fn ($document) => $document->getAttribute('targetInternalId'), $database->find('subscribers', [ diff --git a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php index 3a17d62ff4..8533c5baa0 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php @@ -115,7 +115,12 @@ class XList extends Action $selectQueries = Query::groupByType($queries)['selections'] ?? []; $filterQueries = Query::groupByType($queries)['filters']; - $projects = $this->find($dbForPlatform, $queries, $selectQueries); + /** + * Add filters which do not exist in response model? + */ + $filtersToSkip = []; + $projects = $dbForPlatform->skipFilters(fn () => $dbForPlatform->find('projects', $queries), $filtersToSkip); + $total = $includeTotal ? $dbForPlatform->count('projects', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (Order $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); @@ -128,71 +133,4 @@ class XList extends Action 'total' => $total, ]), Response::MODEL_PROJECT_LIST); } - - // Build mapping of columns to their subQuery filters - private static function getAttributeToSubQueryFilters(): array - { - if (self::$attributeToSubQueryFilters !== null) { - return self::$attributeToSubQueryFilters; - } - - self::$attributeToSubQueryFilters = []; - - $collections = Config::getParam('collections', []); - $projectAttributes = $collections['platform']['projects']['attributes'] ?? []; - - foreach ($projectAttributes as $attribute) { - $attributeId = $attribute['$id'] ?? null; - $filters = $attribute['filters'] ?? []; - - if ($attributeId === null || empty($filters)) { - continue; - } - - // extract only subQuery filters - $subQueryFilters = \array_filter($filters, function ($filter) { - return \str_starts_with($filter, 'subQuery'); - }); - - if (!empty($subQueryFilters)) { - self::$attributeToSubQueryFilters[$attributeId] = \array_values($subQueryFilters); - } - } - - return self::$attributeToSubQueryFilters; - } - - private function find(Database $dbForPlatform, array $queries, array $selectQueries): array - { - if (empty($selectQueries)) { - return $dbForPlatform->find('projects', $queries); - } - - $selectedAttributes = []; - foreach ($selectQueries as $query) { - $selectedAttributes[] = $query->getAttribute(); - } - - if (\in_array('*', $selectedAttributes)) { - return $dbForPlatform->find('projects', $queries); - } - - $filtersToSkipMap = []; - $selectedAttributesMap = \array_flip($selectedAttributes); - $attributeToSubQueryFilters = self::getAttributeToSubQueryFilters(); - - foreach ($attributeToSubQueryFilters as $attributeName => $subQueryFilters) { - if (!isset($selectedAttributesMap[$attributeName])) { - foreach ($subQueryFilters as $filter) { - $filtersToSkipMap[$filter] = true; - } - } - } - - $filtersToSkip = \array_keys($filtersToSkipMap); - - return empty($filtersToSkip) - ? $dbForPlatform->find('projects', $queries) - : $dbForPlatform->skipFilters(fn () => $dbForPlatform->find('projects', $queries), $filtersToSkip); - } }