Implement select query validation and dynamic subquery filtering for users

Co-authored-by: jakeb994 <jakeb994@gmail.com>
This commit is contained in:
Cursor Agent
2025-08-12 12:11:49 +00:00
parent f81fd16d26
commit f5d39f8a95
3 changed files with 109 additions and 1 deletions
@@ -11,6 +11,7 @@ use Utopia\Database\Validator\Query\Filter;
use Utopia\Database\Validator\Query\Limit;
use Utopia\Database\Validator\Query\Offset;
use Utopia\Database\Validator\Query\Order;
use Appwrite\Utopia\Database\Validator\Query\Select;
class Base extends Queries
{
@@ -82,6 +83,7 @@ class Base extends Queries
new Cursor(),
new Filter($attributes, APP_DATABASE_QUERY_MAX_VALUES),
new Order($attributes),
new Select($attributes),
];
parent::__construct($validators);
@@ -0,0 +1,58 @@
<?php
namespace Appwrite\Utopia\Database\Validator\Query;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\Query;
class Select extends Query
{
protected array $schema = [];
/**
* @param Document[] $attributes
*/
public function __construct(array $attributes)
{
foreach ($attributes as $attribute) {
$this->schema[$attribute->getAttribute('key')] = $attribute->getAttribute('type');
}
}
protected function isValidAttribute(string $attribute): bool
{
if (str_starts_with($attribute, '$')) {
return true; // Allow system attributes
}
return array_key_exists($attribute, $this->schema);
}
public function isValid(mixed $query): bool
{
if (!$query instanceof \Utopia\Database\Query) {
return false;
}
if ($query->getMethod() !== Query::TYPE_SELECT) {
return false;
}
$values = $query->getValues();
foreach ($values as $attribute) {
if (!$this->isValidAttribute($attribute)) {
$this->message = 'Query select is not valid: Attribute "' . $attribute . '" not found.';
return false;
}
}
return true;
}
public function getType(): string
{
return Query::TYPE_SELECT;
}
}