Skip to content

Commit d821d1f

Browse files
authored
Merge pull request #264 from utopia-php/appwrite-validators
Appwrite validators transfer
2 parents ba3dcda + 0a1c827 commit d821d1f

31 files changed

+1989
-1487
lines changed

composer.lock

Lines changed: 8 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Database/Adapter/MariaDB.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,7 @@ public function sum(string $collection, string $attribute, array $queries = [],
11781178
* @param array<string> $selections
11791179
* @param string $prefix
11801180
* @return mixed
1181+
* @throws Exception
11811182
*/
11821183
protected function getAttributeProjection(array $selections, string $prefix = ''): mixed
11831184
{
@@ -1196,11 +1197,11 @@ protected function getAttributeProjection(array $selections, string $prefix = ''
11961197

11971198
if (!empty($prefix)) {
11981199
foreach ($selections as &$selection) {
1199-
$selection = "`{$prefix}`.`{$selection}`";
1200+
$selection = "`{$prefix}`.`{$this->filter($selection)}`";
12001201
}
12011202
} else {
12021203
foreach ($selections as &$selection) {
1203-
$selection = "`{$selection}`";
1204+
$selection = "`{$this->filter($selection)}`";
12041205
}
12051206
}
12061207

src/Database/Adapter/Postgres.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,7 @@ public function sum(string $collection, string $attribute, array $queries = [],
11851185
* @param string[] $selections
11861186
* @param string $prefix
11871187
* @return string
1188+
* @throws Exception
11881189
*/
11891190
protected function getAttributeProjection(array $selections, string $prefix = ''): string
11901191
{
@@ -1203,11 +1204,11 @@ protected function getAttributeProjection(array $selections, string $prefix = ''
12031204

12041205
if (!empty($prefix)) {
12051206
foreach ($selections as &$selection) {
1206-
$selection = "\"{$prefix}\".\"{$selection}\"";
1207+
$selection = "\"{$prefix}\".\"{$this->filter($selection)}\"";
12071208
}
12081209
} else {
12091210
foreach ($selections as &$selection) {
1210-
$selection = "\"{$selection}\"";
1211+
$selection = "\"{$this->filter($selection)}\"";
12111212
}
12121213
}
12131214

src/Database/Database.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Utopia\Database\Helpers\Permission;
1717
use Utopia\Database\Helpers\Role;
1818
use Utopia\Database\Validator\Authorization;
19+
use Utopia\Database\Validator\Queries\Documents;
1920
use Utopia\Database\Validator\Index as IndexValidator;
2021
use Utopia\Database\Validator\Permissions;
2122
use Utopia\Database\Validator\Structure;
@@ -3838,6 +3839,13 @@ public function find(string $collection, array $queries = [], ?int $timeout = nu
38383839
}
38393840

38403841
$collection = $this->silent(fn () => $this->getCollection($collection));
3842+
$attributes = $collection->getAttribute('attributes', []);
3843+
$indexes = $collection->getAttribute('indexes', []);
3844+
3845+
$validator = new Documents($attributes, $indexes);
3846+
if (!$validator->isValid($queries)) {
3847+
throw new Exception($validator->getDescription());
3848+
}
38413849

38423850
$authorization = new Authorization(self::PERMISSION_READ);
38433851
$skipAuth = $authorization->isValid($collection->getRead());

src/Database/Query.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -698,11 +698,10 @@ public static function endsWith(string $attribute, string $value): self
698698
* Filters $queries for $types
699699
*
700700
* @param array<Query> $queries
701-
* @param string ...$types
702-
*
701+
* @param array<string> $types
703702
* @return array<Query>
704703
*/
705-
public static function getByType(array $queries, string ...$types): array
704+
public static function getByType(array $queries, array $types): array
706705
{
707706
$filtered = [];
708707
foreach ($queries as $query) {
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
3+
namespace Utopia\Database\Validator;
4+
5+
use Exception;
6+
use Utopia\Database\Database;
7+
use Utopia\Database\Document;
8+
use Utopia\Database\Query;
9+
use Utopia\Database\Validator\Query\Base;
10+
11+
class IndexedQueries extends Queries
12+
{
13+
/**
14+
* @var array<Document>
15+
*/
16+
protected array $attributes = [];
17+
18+
/**
19+
* @var array<Document>
20+
*/
21+
protected array $indexes = [];
22+
23+
/**
24+
* Expression constructor
25+
*
26+
* This Queries Validator filters indexes for only available indexes
27+
*
28+
* @param array<Document> $attributes
29+
* @param array<Document> $indexes
30+
* @param array<Base> $validators
31+
* @throws Exception
32+
*/
33+
public function __construct(array $attributes = [], array $indexes = [], array $validators = [])
34+
{
35+
$this->attributes = $attributes;
36+
37+
$this->indexes[] = new Document([
38+
'type' => Database::INDEX_UNIQUE,
39+
'attributes' => ['$id']
40+
]);
41+
42+
$this->indexes[] = new Document([
43+
'type' => Database::INDEX_KEY,
44+
'attributes' => ['$createdAt']
45+
]);
46+
47+
$this->indexes[] = new Document([
48+
'type' => Database::INDEX_KEY,
49+
'attributes' => ['$updatedAt']
50+
]);
51+
52+
foreach ($indexes as $index) {
53+
$this->indexes[] = $index;
54+
}
55+
56+
parent::__construct($validators);
57+
}
58+
59+
/**
60+
* @param mixed $value
61+
* @return bool
62+
* @throws Exception
63+
*/
64+
public function isValid($value): bool
65+
{
66+
if (!parent::isValid($value)) {
67+
return false;
68+
}
69+
$queries = [];
70+
foreach ($value as $query) {
71+
if (!$query instanceof Query) {
72+
$query = Query::parse($query);
73+
}
74+
75+
$queries[] = $query;
76+
}
77+
78+
$grouped = Query::groupByType($queries);
79+
$filters = $grouped['filters'];
80+
81+
foreach ($filters as $filter) {
82+
if ($filter->getMethod() === Query::TYPE_SEARCH) {
83+
$matched = false;
84+
85+
foreach ($this->indexes as $index) {
86+
if (
87+
$index->getAttribute('type') === Database::INDEX_FULLTEXT
88+
&& $index->getAttribute('attributes') === [$filter->getAttribute()]
89+
) {
90+
$matched = true;
91+
}
92+
}
93+
94+
if (!$matched) {
95+
$this->message = "Searching by attribute \"{$filter->getAttribute()}\" requires a fulltext index.";
96+
return false;
97+
}
98+
}
99+
}
100+
101+
return true;
102+
}
103+
}

0 commit comments

Comments
 (0)