mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch '1.8.x' into new-pool-adapter
This commit is contained in:
@@ -632,30 +632,6 @@ $platformCollections = [
|
||||
'$id' => ID::custom('keys'),
|
||||
'name' => 'keys',
|
||||
'attributes' => [
|
||||
// Delete eventuelly, when removing dual-write too
|
||||
[
|
||||
'$id' => ID::custom('projectInternalId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
// Delete eventuelly, when removing dual-write too
|
||||
[
|
||||
'$id' => ID::custom('projectId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => 0,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('resourceType'),
|
||||
'type' => Database::VAR_STRING,
|
||||
|
||||
@@ -1502,9 +1502,6 @@ App::post('/v1/projects/:projectId/keys')
|
||||
Permission::update(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
// TODO: @hmacr Remove `projectInternalId` and `projectId` column writes before deleting the column.
|
||||
'projectInternalId' => $project->getSequence(),
|
||||
'projectId' => $project->getId(),
|
||||
'resourceInternalId' => $project->getSequence(),
|
||||
'resourceId' => $project->getId(),
|
||||
'resourceType' => 'projects',
|
||||
|
||||
@@ -1228,7 +1228,7 @@ App::error()
|
||||
}
|
||||
|
||||
switch ($class) {
|
||||
case 'Utopia\Exception':
|
||||
case Utopia\Exception::class:
|
||||
$error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error);
|
||||
switch ($code) {
|
||||
case 400:
|
||||
@@ -1239,10 +1239,10 @@ App::error()
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'Utopia\Database\Exception\Authorization':
|
||||
case Utopia\Database\Exception\Authorization::class:
|
||||
$error = new AppwriteException(AppwriteException::USER_UNAUTHORIZED);
|
||||
break;
|
||||
case 'Utopia\Database\Exception\Timeout':
|
||||
case Utopia\Database\Exception\Timeout::class:
|
||||
$error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -200,9 +200,6 @@ App::post('/v1/mock/api-key-unprefixed')
|
||||
Permission::update(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
// TODO: @hmacr Remove `projectInternalId` and `projectId` column writes before deleting the column.
|
||||
'projectInternalId' => $project->getSequence(),
|
||||
'projectId' => $project->getId(),
|
||||
'resourceInternalId' => $project->getSequence(),
|
||||
'resourceId' => $project->getId(),
|
||||
'resourceType' => 'projects',
|
||||
|
||||
Generated
+18
-18
@@ -2066,16 +2066,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "3.0.48",
|
||||
"version": "3.0.49",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "64065a5679c50acb886e82c07aa139b0f757bb89"
|
||||
"reference": "6233a1e12584754e6b5daa69fe1289b47775c1b9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/64065a5679c50acb886e82c07aa139b0f757bb89",
|
||||
"reference": "64065a5679c50acb886e82c07aa139b0f757bb89",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/6233a1e12584754e6b5daa69fe1289b47775c1b9",
|
||||
"reference": "6233a1e12584754e6b5daa69fe1289b47775c1b9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2156,7 +2156,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpseclib/phpseclib/issues",
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.48"
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.49"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2172,7 +2172,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-12-15T11:51:42+00:00"
|
||||
"time": "2026-01-27T09:17:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -8200,16 +8200,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v8.0.4",
|
||||
"version": "v8.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "42e48eb02e07d5f3771d194d67da117eb824c8c1"
|
||||
"reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/42e48eb02e07d5f3771d194d67da117eb824c8c1",
|
||||
"reference": "42e48eb02e07d5f3771d194d67da117eb824c8c1",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/8bd576e97c67d45941365bf824e18dc8538e6eb0",
|
||||
"reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -8244,7 +8244,7 @@
|
||||
"description": "Finds files and directories via an intuitive fluent interface",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/finder/tree/v8.0.4"
|
||||
"source": "https://github.com/symfony/finder/tree/v8.0.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -8264,7 +8264,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-12T12:37:40+00:00"
|
||||
"time": "2026-01-26T15:08:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
@@ -8669,16 +8669,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v8.0.4",
|
||||
"version": "v8.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "10df72602d88c0a3fa685b822976a052611dd607"
|
||||
"reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/10df72602d88c0a3fa685b822976a052611dd607",
|
||||
"reference": "10df72602d88c0a3fa685b822976a052611dd607",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674",
|
||||
"reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -8710,7 +8710,7 @@
|
||||
"description": "Executes commands in sub-processes",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/v8.0.4"
|
||||
"source": "https://github.com/symfony/process/tree/v8.0.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -8730,7 +8730,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-23T11:07:10+00:00"
|
||||
"time": "2026-01-26T15:08:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
|
||||
@@ -269,59 +269,59 @@ class Mapper
|
||||
}
|
||||
|
||||
switch ((!empty($validator)) ? $validator::class : '') {
|
||||
case 'Appwrite\Auth\Validator\Password':
|
||||
case 'Appwrite\Event\Validator\Event':
|
||||
case 'Appwrite\Event\Validator\FunctionEvent':
|
||||
case 'Appwrite\Network\Validator\CNAME':
|
||||
case 'Appwrite\Network\Validator\Email':
|
||||
case 'Appwrite\Network\Validator\Redirect':
|
||||
case 'Appwrite\Network\Validator\DNS':
|
||||
case 'Appwrite\Network\Validator\Origin':
|
||||
case 'Appwrite\Task\Validator\Cron':
|
||||
case 'Appwrite\Utopia\Database\Validator\CustomId':
|
||||
case 'Utopia\Database\Validator\Key':
|
||||
case 'Utopia\Database\Validator\UID':
|
||||
case 'Utopia\Validator\Domain':
|
||||
case 'Utopia\Validator\HexColor':
|
||||
case 'Utopia\Validator\Host':
|
||||
case 'Utopia\Validator\IP':
|
||||
case 'Utopia\Validator\Origin':
|
||||
case 'Utopia\Validator\Text':
|
||||
case 'Utopia\Validator\URL':
|
||||
case 'Utopia\Validator\WhiteList':
|
||||
case \Appwrite\Auth\Validator\Password::class:
|
||||
case \Appwrite\Event\Validator\Event::class:
|
||||
case \Appwrite\Event\Validator\FunctionEvent::class:
|
||||
case \Appwrite\Network\Validator\CNAME::class:
|
||||
case \Appwrite\Network\Validator\Email::class:
|
||||
case \Appwrite\Network\Validator\Redirect::class:
|
||||
case \Appwrite\Network\Validator\DNS::class:
|
||||
case \Appwrite\Network\Validator\Origin::class:
|
||||
case \Appwrite\Task\Validator\Cron::class:
|
||||
case \Appwrite\Utopia\Database\Validator\CustomId::class:
|
||||
case \Utopia\Database\Validator\Key::class:
|
||||
case \Utopia\Database\Validator\UID::class:
|
||||
case \Utopia\Validator\Domain::class:
|
||||
case \Utopia\Validator\HexColor::class:
|
||||
case \Utopia\Validator\Host::class:
|
||||
case \Utopia\Validator\IP::class:
|
||||
case \Utopia\Validator\Origin::class:
|
||||
case \Utopia\Validator\Text::class:
|
||||
case \Utopia\Validator\URL::class:
|
||||
case \Utopia\Validator\WhiteList::class:
|
||||
default:
|
||||
$type = Type::string();
|
||||
break;
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Attributes':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Base':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Buckets':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Tables':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Collections':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Columns':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Databases':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Deployments':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Executions':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Files':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Functions':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Indexes':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Installations':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Memberships':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Projects':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Rules':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Teams':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Users':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Variables':
|
||||
case 'Utopia\Database\Validator\Authorization':
|
||||
case 'Utopia\Database\Validator\Permissions':
|
||||
case 'Utopia\Database\Validator\Queries':
|
||||
case 'Utopia\Database\Validator\Queries\Documents':
|
||||
case 'Utopia\Database\Validator\Roles':
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Attributes::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Base::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Buckets::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Tables::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Collections::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Columns::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Databases::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Deployments::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Executions::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Files::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Functions::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Indexes::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Installations::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Memberships::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Projects::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Rules::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Teams::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Users::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Variables::class:
|
||||
case \Utopia\Database\Validator\Authorization::class:
|
||||
case \Utopia\Database\Validator\Permissions::class:
|
||||
case \Utopia\Database\Validator\Queries::class:
|
||||
case \Utopia\Database\Validator\Queries\Documents::class:
|
||||
case \Utopia\Database\Validator\Roles::class:
|
||||
$type = Type::listOf(Type::string());
|
||||
break;
|
||||
case 'Utopia\Validator\Boolean':
|
||||
case \Utopia\Validator\Boolean::class:
|
||||
$type = Type::boolean();
|
||||
break;
|
||||
case 'Utopia\Validator\ArrayList':
|
||||
case \Utopia\Validator\ArrayList::class:
|
||||
$type = Type::listOf(self::param(
|
||||
$utopia,
|
||||
$validator->getValidator(),
|
||||
@@ -329,11 +329,11 @@ class Mapper
|
||||
$injections
|
||||
));
|
||||
break;
|
||||
case 'Utopia\Validator\Integer':
|
||||
case 'Utopia\Validator\Numeric':
|
||||
case \Utopia\Validator\Integer::class:
|
||||
case \Utopia\Validator\Numeric::class:
|
||||
$type = Type::int();
|
||||
break;
|
||||
case 'Utopia\Validator\Range':
|
||||
case \Utopia\Validator\Range::class:
|
||||
// Check if the Range validator is for float or integer
|
||||
if ($validator instanceof \Utopia\Validator\Range && $validator->getType() === \Utopia\Validator\Range::TYPE_FLOAT) {
|
||||
$type = Type::float();
|
||||
@@ -341,16 +341,16 @@ class Mapper
|
||||
$type = Type::int();
|
||||
}
|
||||
break;
|
||||
case 'Utopia\Validator\FloatValidator':
|
||||
case \Utopia\Validator\FloatValidator::class:
|
||||
$type = Type::float();
|
||||
break;
|
||||
case 'Utopia\Validator\Assoc':
|
||||
case \Utopia\Validator\Assoc::class:
|
||||
$type = Types::assoc();
|
||||
break;
|
||||
case 'Utopia\Validator\JSON':
|
||||
case \Utopia\Validator\JSON::class:
|
||||
$type = Types::json();
|
||||
break;
|
||||
case 'Utopia\Storage\Validator\File':
|
||||
case \Utopia\Storage\Validator\File::class:
|
||||
$type = Types::inputFile();
|
||||
break;
|
||||
}
|
||||
|
||||
+30
@@ -6,6 +6,7 @@ use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Functions\EventProcessor;
|
||||
use Appwrite\Platform\Modules\Databases\Http\Databases\Action as DatabasesAction;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
@@ -250,6 +251,35 @@ abstract class Action extends DatabasesAction
|
||||
return $document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate relationship values.
|
||||
* Handles Document objects, ID strings, and associative arrays.
|
||||
*/
|
||||
protected function validateRelationship(mixed $relation): void
|
||||
{
|
||||
$relationId = null;
|
||||
|
||||
if ($relation instanceof Document) {
|
||||
$relationId = $relation->getId();
|
||||
} elseif (\is_string($relation)) {
|
||||
$relationId = $relation;
|
||||
} elseif (\is_array($relation) && !\array_is_list($relation)) {
|
||||
$relationId = $relation['$id'] ?? null;
|
||||
} else {
|
||||
throw new Exception(Exception::RELATIONSHIP_VALUE_INVALID, 'Relationship value must be an object, document ID string, or associative array');
|
||||
}
|
||||
|
||||
if ($relationId !== null) {
|
||||
if (!\is_string($relationId)) {
|
||||
throw new Exception(Exception::RELATIONSHIP_VALUE_INVALID, 'Relationship $id must be a string');
|
||||
}
|
||||
$validator = new CustomId();
|
||||
if (!$validator->isValid($relationId)) {
|
||||
throw new Exception(Exception::RELATIONSHIP_VALUE_INVALID, $validator->getDescription());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves relationships in a document and attaches metadata.
|
||||
*/
|
||||
|
||||
+3
@@ -319,6 +319,9 @@ class Create extends Action
|
||||
$relation['$id'] = ID::unique();
|
||||
$relation = new Document($relation);
|
||||
}
|
||||
|
||||
$this->validateRelationship($relation);
|
||||
|
||||
if ($relation instanceof Document) {
|
||||
$relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser);
|
||||
|
||||
|
||||
+3
@@ -210,6 +210,9 @@ class Update extends Action
|
||||
$relation['$id'] = ID::unique();
|
||||
$relation = new Document($relation);
|
||||
}
|
||||
|
||||
$this->validateRelationship($relation);
|
||||
|
||||
if ($relation instanceof Document) {
|
||||
$relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser);
|
||||
|
||||
|
||||
+3
@@ -220,6 +220,9 @@ class Upsert extends Action
|
||||
$relation['$id'] = ID::unique();
|
||||
$relation = new Document($relation);
|
||||
}
|
||||
|
||||
$this->validateRelationship($relation);
|
||||
|
||||
if ($relation instanceof Document) {
|
||||
$relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser);
|
||||
|
||||
|
||||
@@ -392,51 +392,51 @@ class OpenAPI3 extends Format
|
||||
: '';
|
||||
|
||||
switch ($base) {
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Base':
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Base::class:
|
||||
$class = $base;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($class === 'Utopia\Validator\AnyOf') {
|
||||
if ($class === \Utopia\Validator\AnyOf::class) {
|
||||
$validator = $param['validator']->getValidators()[0];
|
||||
$class = \get_class($validator);
|
||||
}
|
||||
|
||||
$array = false;
|
||||
if ($class === 'Utopia\Validator\ArrayList') {
|
||||
if ($class === \Utopia\Validator\ArrayList::class) {
|
||||
$array = true;
|
||||
$subclass = \get_class($validator->getValidator());
|
||||
switch ($subclass) {
|
||||
case 'Appwrite\Utopia\Database\Validator\Operation':
|
||||
case 'Utopia\Validator\WhiteList':
|
||||
case \Appwrite\Utopia\Database\Validator\Operation::class:
|
||||
case \Utopia\Validator\WhiteList::class:
|
||||
$class = $subclass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch ($class) {
|
||||
case 'Utopia\Database\Validator\UID':
|
||||
case 'Utopia\Validator\Text':
|
||||
case \Utopia\Database\Validator\UID::class:
|
||||
case \Utopia\Validator\Text::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>';
|
||||
break;
|
||||
case 'Utopia\Validator\Boolean':
|
||||
case \Utopia\Validator\Boolean::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: false;
|
||||
break;
|
||||
case 'Appwrite\Utopia\Database\Validator\CustomId':
|
||||
case \Appwrite\Utopia\Database\Validator\CustomId::class:
|
||||
if ($sdk->getType() === MethodType::UPLOAD) {
|
||||
$node['schema']['x-upload-id'] = true;
|
||||
}
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>';
|
||||
break;
|
||||
case 'Utopia\Database\Validator\DatetimeValidator':
|
||||
case \Utopia\Database\Validator\DatetimeValidator::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['format'] = 'datetime';
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: Model::TYPE_DATETIME_EXAMPLE;
|
||||
break;
|
||||
case 'Utopia\Database\Validator\Spatial':
|
||||
case \Utopia\Database\Validator\Spatial::class:
|
||||
/** @var Spatial $validator */
|
||||
$node['schema']['type'] = 'array';
|
||||
$node['schema']['items'] = [
|
||||
@@ -450,31 +450,31 @@ class OpenAPI3 extends Format
|
||||
Database::VAR_POLYGON => '[[[1, 2], [3, 4], [5, 6], [1, 2]]]',
|
||||
};
|
||||
break;
|
||||
case 'Appwrite\Network\Validator\Email':
|
||||
case \Appwrite\Network\Validator\Email::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['format'] = 'email';
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: 'email@example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\Host':
|
||||
case 'Utopia\Validator\URL':
|
||||
case 'Appwrite\Network\Validator\Redirect':
|
||||
case \Utopia\Validator\Host::class:
|
||||
case \Utopia\Validator\URL::class:
|
||||
case \Appwrite\Network\Validator\Redirect::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['format'] = 'url';
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: 'https://example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\JSON':
|
||||
case 'Utopia\Validator\Mock':
|
||||
case 'Utopia\Validator\Assoc':
|
||||
case \Utopia\Validator\JSON::class:
|
||||
case \Utopia\Validator\Mock::class:
|
||||
case \Utopia\Validator\Assoc::class:
|
||||
$param['default'] = (empty($param['default'])) ? new \stdClass() : $param['default'];
|
||||
$node['schema']['type'] = 'object';
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: '{}';
|
||||
break;
|
||||
case 'Utopia\Storage\Validator\File':
|
||||
case \Utopia\Storage\Validator\File::class:
|
||||
$consumes = ['multipart/form-data'];
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['format'] = 'binary';
|
||||
break;
|
||||
case 'Utopia\Validator\ArrayList':
|
||||
case \Utopia\Validator\ArrayList::class:
|
||||
/** @var ArrayList $validator */
|
||||
$node['schema']['type'] = 'array';
|
||||
$node['schema']['items'] = [
|
||||
@@ -484,92 +484,92 @@ class OpenAPI3 extends Format
|
||||
$node['schema']['x-example'] = $param['example'];
|
||||
}
|
||||
break;
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Base':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Columns':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Attributes':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Buckets':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Tables':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Collections':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Databases':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Deployments':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Executions':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Files':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Functions':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Identities':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Indexes':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Installations':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Memberships':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Messages':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Migrations':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Projects':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Providers':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Rules':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Subscribers':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Targets':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Teams':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Topics':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Users':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Variables':
|
||||
case 'Utopia\Database\Validator\Queries':
|
||||
case 'Utopia\Database\Validator\Queries\Document':
|
||||
case 'Utopia\Database\Validator\Queries\Documents':
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Base::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Columns::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Attributes::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Buckets::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Tables::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Collections::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Databases::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Deployments::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Executions::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Files::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Functions::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Identities::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Indexes::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Installations::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Memberships::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Messages::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Migrations::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Projects::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Providers::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Rules::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Subscribers::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Targets::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Teams::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Topics::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Users::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Variables::class:
|
||||
case \Utopia\Database\Validator\Queries::class:
|
||||
case \Utopia\Database\Validator\Queries\Document::class:
|
||||
case \Utopia\Database\Validator\Queries\Documents::class:
|
||||
$node['schema']['type'] = 'array';
|
||||
$node['schema']['items'] = [
|
||||
'type' => 'string',
|
||||
];
|
||||
break;
|
||||
case 'Utopia\Database\Validator\Permissions':
|
||||
case \Utopia\Database\Validator\Permissions::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['items'] = [
|
||||
'type' => 'string',
|
||||
];
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: '["' . Permission::read(Role::any()) . '"]';
|
||||
break;
|
||||
case 'Utopia\Database\Validator\Roles':
|
||||
case \Utopia\Database\Validator\Roles::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['items'] = [
|
||||
'type' => 'string',
|
||||
];
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: '["' . Role::any()->toString() . '"]';
|
||||
break;
|
||||
case 'Appwrite\Auth\Validator\Password':
|
||||
case \Appwrite\Auth\Validator\Password::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['format'] = 'password';
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: 'password';
|
||||
break;
|
||||
case 'Appwrite\Auth\Validator\Phone':
|
||||
case \Appwrite\Auth\Validator\Phone::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['format'] = 'phone';
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: '+12065550100'; // In the US, 555 is reserved like example.com
|
||||
break;
|
||||
case 'Utopia\Validator\Range':
|
||||
case \Utopia\Validator\Range::class:
|
||||
/** @var Range $validator */
|
||||
$node['schema']['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType();
|
||||
$node['schema']['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float';
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: $validator->getMin();
|
||||
break;
|
||||
case 'Utopia\Validator\Integer':
|
||||
case \Utopia\Validator\Integer::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['format'] = $validator->getFormat();
|
||||
if (!empty($param['example'])) {
|
||||
$node['schema']['x-example'] = $param['example'];
|
||||
}
|
||||
break;
|
||||
case 'Utopia\Validator\Numeric':
|
||||
case 'Utopia\Validator\FloatValidator':
|
||||
case \Utopia\Validator\Numeric::class:
|
||||
case \Utopia\Validator\FloatValidator::class:
|
||||
$node['schema']['type'] = 'number';
|
||||
$node['schema']['format'] = 'float';
|
||||
if (!empty($param['example'])) {
|
||||
$node['schema']['x-example'] = $param['example'];
|
||||
}
|
||||
break;
|
||||
case 'Utopia\Validator\Length':
|
||||
case \Utopia\Validator\Length::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
if (!empty($param['example'])) {
|
||||
$node['schema']['x-example'] = $param['example'];
|
||||
}
|
||||
break;
|
||||
case 'Utopia\Validator\WhiteList':
|
||||
case \Utopia\Validator\WhiteList::class:
|
||||
if ($array) {
|
||||
$validator = $validator->getValidator();
|
||||
|
||||
@@ -687,11 +687,11 @@ class OpenAPI3 extends Format
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Appwrite\Utopia\Database\Validator\CompoundUID':
|
||||
case \Appwrite\Utopia\Database\Validator\CompoundUID::class:
|
||||
$node['schema']['type'] = $validator->getType();
|
||||
$node['schema']['x-example'] = ($param['example'] ?? '') ?: '<ID1:ID2>';
|
||||
break;
|
||||
case 'Appwrite\Utopia\Database\Validator\Operation':
|
||||
case \Appwrite\Utopia\Database\Validator\Operation::class:
|
||||
if ($array) {
|
||||
$validator = $validator->getValidator();
|
||||
}
|
||||
|
||||
@@ -397,51 +397,51 @@ class Swagger2 extends Format
|
||||
: '';
|
||||
|
||||
switch ($base) {
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Base':
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Base::class:
|
||||
$class = $base;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($class === 'Utopia\Validator\AnyOf') {
|
||||
if ($class === \Utopia\Validator\AnyOf::class) {
|
||||
$validator = $param['validator']->getValidators()[0];
|
||||
$class = \get_class($validator);
|
||||
}
|
||||
|
||||
$array = false;
|
||||
if ($class === 'Utopia\Validator\ArrayList') {
|
||||
if ($class === \Utopia\Validator\ArrayList::class) {
|
||||
$array = true;
|
||||
$subclass = \get_class($validator->getValidator());
|
||||
switch ($subclass) {
|
||||
case 'Appwrite\Utopia\Database\Validator\Operation':
|
||||
case 'Utopia\Validator\WhiteList':
|
||||
case \Appwrite\Utopia\Database\Validator\Operation::class:
|
||||
case \Utopia\Validator\WhiteList::class:
|
||||
$class = $subclass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch ($class) {
|
||||
case 'Utopia\Validator\Text':
|
||||
case 'Utopia\Database\Validator\UID':
|
||||
case \Utopia\Validator\Text::class:
|
||||
case \Utopia\Database\Validator\UID::class:
|
||||
$node['type'] = $validator->getType();
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>';
|
||||
break;
|
||||
case 'Utopia\Validator\Boolean':
|
||||
case \Utopia\Validator\Boolean::class:
|
||||
$node['type'] = $validator->getType();
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: false;
|
||||
break;
|
||||
case 'Appwrite\Utopia\Database\Validator\CustomId':
|
||||
case \Appwrite\Utopia\Database\Validator\CustomId::class:
|
||||
if ($sdk->getType() === MethodType::UPLOAD) {
|
||||
$node['x-upload-id'] = true;
|
||||
}
|
||||
$node['type'] = $validator->getType();
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>';
|
||||
break;
|
||||
case 'Utopia\Database\Validator\DatetimeValidator':
|
||||
case \Utopia\Database\Validator\DatetimeValidator::class:
|
||||
$node['type'] = $validator->getType();
|
||||
$node['format'] = 'datetime';
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: Model::TYPE_DATETIME_EXAMPLE;
|
||||
break;
|
||||
case 'Utopia\Database\Validator\Spatial':
|
||||
case \Utopia\Database\Validator\Spatial::class:
|
||||
/** @var Spatial $validator */
|
||||
$node['type'] = 'array';
|
||||
$node['schema']['items'] = [
|
||||
@@ -455,19 +455,19 @@ class Swagger2 extends Format
|
||||
Database::VAR_POLYGON => '[[[1, 2], [3, 4], [5, 6], [1, 2]]]',
|
||||
};
|
||||
break;
|
||||
case 'Appwrite\Network\Validator\Email':
|
||||
case \Appwrite\Network\Validator\Email::class:
|
||||
$node['type'] = $validator->getType();
|
||||
$node['format'] = 'email';
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: 'email@example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\Host':
|
||||
case 'Utopia\Validator\URL':
|
||||
case 'Appwrite\Network\Validator\Redirect':
|
||||
case \Utopia\Validator\Host::class:
|
||||
case \Utopia\Validator\URL::class:
|
||||
case \Appwrite\Network\Validator\Redirect::class:
|
||||
$node['type'] = $validator->getType();
|
||||
$node['format'] = 'url';
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: 'https://example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\ArrayList':
|
||||
case \Utopia\Validator\ArrayList::class:
|
||||
/** @var ArrayList $validator */
|
||||
$node['type'] = 'array';
|
||||
$node['collectionFormat'] = 'multi';
|
||||
@@ -478,34 +478,34 @@ class Swagger2 extends Format
|
||||
$node['x-example'] = $param['example'];
|
||||
}
|
||||
break;
|
||||
case 'Utopia\Validator\JSON':
|
||||
case 'Utopia\Validator\Mock':
|
||||
case 'Utopia\Validator\Assoc':
|
||||
case \Utopia\Validator\JSON::class:
|
||||
case \Utopia\Validator\Mock::class:
|
||||
case \Utopia\Validator\Assoc::class:
|
||||
$node['type'] = 'object';
|
||||
$node['default'] = (empty($param['default'])) ? new \stdClass() : $param['default'];
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: '{}';
|
||||
break;
|
||||
case 'Utopia\Storage\Validator\File':
|
||||
case \Utopia\Storage\Validator\File::class:
|
||||
$consumes = ['multipart/form-data'];
|
||||
$node['type'] = 'file';
|
||||
break;
|
||||
case 'Appwrite\Functions\Validator\Payload':
|
||||
case \Appwrite\Functions\Validator\Payload::class:
|
||||
$consumes = ['multipart/form-data'];
|
||||
$node['type'] = 'payload';
|
||||
break;
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Base':
|
||||
case 'Utopia\Database\Validator\Queries':
|
||||
case 'Utopia\Database\Validator\Queries\Document':
|
||||
case 'Utopia\Database\Validator\Queries\Documents':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Columns':
|
||||
case 'Appwrite\Utopia\Database\Validator\Queries\Tables':
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Base::class:
|
||||
case \Utopia\Database\Validator\Queries::class:
|
||||
case \Utopia\Database\Validator\Queries\Document::class:
|
||||
case \Utopia\Database\Validator\Queries\Documents::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Columns::class:
|
||||
case \Appwrite\Utopia\Database\Validator\Queries\Tables::class:
|
||||
$node['type'] = 'array';
|
||||
$node['collectionFormat'] = 'multi';
|
||||
$node['items'] = [
|
||||
'type' => 'string',
|
||||
];
|
||||
break;
|
||||
case 'Utopia\Database\Validator\Permissions':
|
||||
case \Utopia\Database\Validator\Permissions::class:
|
||||
$node['type'] = $validator->getType();
|
||||
$node['collectionFormat'] = 'multi';
|
||||
$node['items'] = [
|
||||
@@ -513,7 +513,7 @@ class Swagger2 extends Format
|
||||
];
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: '["' . Permission::read(Role::any()) . '"]';
|
||||
break;
|
||||
case 'Utopia\Database\Validator\Roles':
|
||||
case \Utopia\Database\Validator\Roles::class:
|
||||
$node['type'] = $validator->getType();
|
||||
$node['collectionFormat'] = 'multi';
|
||||
$node['items'] = [
|
||||
@@ -521,44 +521,44 @@ class Swagger2 extends Format
|
||||
];
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: '["' . Role::any()->toString() . '"]';
|
||||
break;
|
||||
case 'Appwrite\Auth\Validator\Password':
|
||||
case \Appwrite\Auth\Validator\Password::class:
|
||||
$node['type'] = $validator->getType();
|
||||
$node['format'] = 'password';
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: 'password';
|
||||
break;
|
||||
case 'Appwrite\Auth\Validator\Phone':
|
||||
case \Appwrite\Auth\Validator\Phone::class:
|
||||
$node['type'] = $validator->getType();
|
||||
$node['format'] = 'phone';
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: '+12065550100';
|
||||
break;
|
||||
case 'Utopia\Validator\Range':
|
||||
case \Utopia\Validator\Range::class:
|
||||
/** @var Range $validator */
|
||||
$node['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType();
|
||||
$node['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float';
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: $validator->getMin();
|
||||
break;
|
||||
case 'Utopia\Validator\Integer':
|
||||
case \Utopia\Validator\Integer::class:
|
||||
$node['type'] = $validator->getType();
|
||||
$node['format'] = $validator->getFormat();
|
||||
if (!empty($param['example'])) {
|
||||
$node['x-example'] = $param['example'];
|
||||
}
|
||||
break;
|
||||
case 'Utopia\Validator\Numeric':
|
||||
case 'Utopia\Validator\FloatValidator':
|
||||
case \Utopia\Validator\Numeric::class:
|
||||
case \Utopia\Validator\FloatValidator::class:
|
||||
$node['type'] = 'number';
|
||||
$node['format'] = 'float';
|
||||
if (!empty($param['example'])) {
|
||||
$node['x-example'] = $param['example'];
|
||||
}
|
||||
break;
|
||||
case 'Utopia\Validator\Length':
|
||||
case \Utopia\Validator\Length::class:
|
||||
$node['type'] = $validator->getType();
|
||||
if (!empty($param['example'])) {
|
||||
$node['x-example'] = $param['example'];
|
||||
}
|
||||
break;
|
||||
case 'Utopia\Validator\WhiteList':
|
||||
case \Utopia\Validator\WhiteList::class:
|
||||
if ($array) {
|
||||
$validator = $validator->getValidator();
|
||||
|
||||
@@ -665,11 +665,11 @@ class Swagger2 extends Format
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Appwrite\Utopia\Database\Validator\CompoundUID':
|
||||
case \Appwrite\Utopia\Database\Validator\CompoundUID::class:
|
||||
$node['type'] = $validator->getType();
|
||||
$node['x-example'] = ($param['example'] ?? '') ?: '<ID1:ID2>';
|
||||
break;
|
||||
case 'Appwrite\Utopia\Database\Validator\Operation':
|
||||
case \Appwrite\Utopia\Database\Validator\Operation::class:
|
||||
if ($array) {
|
||||
$validator = $validator->getValidator();
|
||||
}
|
||||
|
||||
@@ -7626,6 +7626,267 @@ trait DatabasesBase
|
||||
$this->assertEquals(200, $update['headers']['status-code']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreateDatabase
|
||||
*/
|
||||
public function testInvalidRelationshipDocumentId(array $data): void
|
||||
{
|
||||
$databaseId = $data['databaseId'];
|
||||
|
||||
// Create parent table
|
||||
$parentTable = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'tableId' => ID::unique(),
|
||||
'name' => 'ParentTable',
|
||||
]);
|
||||
$this->assertEquals(201, $parentTable['headers']['status-code']);
|
||||
$parentTableId = $parentTable['body']['$id'];
|
||||
|
||||
// Create child table
|
||||
$childTable = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'tableId' => ID::unique(),
|
||||
'name' => 'ChildTable',
|
||||
]);
|
||||
$this->assertEquals(201, $childTable['headers']['status-code']);
|
||||
$childTableId = $childTable['body']['$id'];
|
||||
|
||||
// Add string column to parent
|
||||
$this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/columns/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'name',
|
||||
'size' => 255,
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
// Add string column to child
|
||||
$this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $childTableId . '/columns/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'title',
|
||||
'size' => 255,
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
// Create one-to-many relationship
|
||||
$relationship = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/columns/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedTableId' => $childTableId,
|
||||
'type' => Database::RELATION_ONE_TO_MANY,
|
||||
'twoWay' => false,
|
||||
'key' => 'children',
|
||||
]);
|
||||
$this->assertEquals(202, $relationship['headers']['status-code']);
|
||||
|
||||
// Wait for relationship column to be available
|
||||
$this->assertEventually(function () use ($databaseId, $parentTableId) {
|
||||
$columns = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/columns', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
$columnKeys = array_column($columns['body']['columns'], 'key');
|
||||
$this->assertContains('children', $columnKeys, "Relationship column 'children' not found in table {$parentTableId} of database {$databaseId}");
|
||||
}, 2000, 200);
|
||||
|
||||
// ID too long (>36 chars) should fail
|
||||
$response = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Parent 1',
|
||||
'children' => [
|
||||
[
|
||||
'$id' => 'this_id_is_way_too_long_and_should_fail_validation_check',
|
||||
'title' => 'Child 1',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// ID with invalid characters should fail
|
||||
$response = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Parent 2',
|
||||
'children' => [
|
||||
[
|
||||
'$id' => 'invalid@id#with$special%chars',
|
||||
'title' => 'Child 2',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// ID starting with underscore should fail
|
||||
$response = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Parent 3',
|
||||
'children' => [
|
||||
[
|
||||
'$id' => '_startsWithUnderscore',
|
||||
'title' => 'Child 3',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Valid ID should succeed
|
||||
$response = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Parent 4',
|
||||
'children' => [
|
||||
[
|
||||
'$id' => 'valid-id-123',
|
||||
'title' => 'Child 4',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$parentRowId = $response['body']['$id'];
|
||||
|
||||
// Update with invalid relationship ID should fail
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/rows/' . $parentRowId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'children' => [
|
||||
[
|
||||
'$id' => 'another@invalid#id',
|
||||
'title' => 'Child 5',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Invalid string relation ID should fail
|
||||
$response = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Parent 6',
|
||||
'children' => [
|
||||
'invalid@string#id',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Integer as relation value should fail
|
||||
$response = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Parent 7',
|
||||
'children' => [
|
||||
12345,
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// unique() as $id should succeed
|
||||
$response = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Parent 8',
|
||||
'children' => [
|
||||
[
|
||||
'$id' => 'unique()',
|
||||
'title' => 'Child 8',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
|
||||
// Empty string as $id should fail
|
||||
$response = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Parent 9',
|
||||
'children' => [
|
||||
[
|
||||
'$id' => '',
|
||||
'title' => 'Child 9',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Valid ID with allowed special chars (hyphen, period) should succeed
|
||||
$response = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $parentTableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Parent 10',
|
||||
'children' => [
|
||||
[
|
||||
'$id' => 'valid.id-with_chars',
|
||||
'title' => 'Child 10',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreateDatabase
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user