mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
tests
This commit is contained in:
@@ -1640,8 +1640,55 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati
|
||||
Event $queueForEvents
|
||||
) {
|
||||
$key ??= $relatedCollectionId;
|
||||
$twoWayKeyNull = is_null($twoWayKey);
|
||||
$twoWayKey ??= $collectionId;
|
||||
|
||||
$databaseDocument = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($databaseDocument->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$collectionDocument = $dbForProject->getDocument('database_' . $databaseDocument->getInternalId(), $collectionId);
|
||||
$collection = $dbForProject->getCollection('database_' . $databaseDocument->getInternalId() . '_collection_' . $collectionDocument->getInternalId());
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$relatedCollectionDocument = $dbForProject->getDocument('database_' . $databaseDocument->getInternalId(), $relatedCollectionId);
|
||||
$relatedCollection = $dbForProject->getCollection('database_' . $databaseDocument->getInternalId() . '_collection_' . $relatedCollectionDocument->getInternalId());
|
||||
|
||||
if ($relatedCollection->isEmpty()) {
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$attributes = $collection->getAttribute('attributes', []);
|
||||
/** @var Document[] $attributes */
|
||||
foreach ($attributes as $attribute) {
|
||||
if (\strtolower($attribute->getId()) === \strtolower($key)) {
|
||||
throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
if (
|
||||
$attribute->getAttribute('type') === Database::VAR_RELATIONSHIP &&
|
||||
\strtolower($attribute->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) &&
|
||||
$attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId()
|
||||
) {
|
||||
// Currently, we always throw an Exception even when, We do not want to change $twoWayKsy on $twoWayKeyNull
|
||||
throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
if (
|
||||
$type === Database::RELATION_MANY_TO_MANY &&
|
||||
$attribute->getAttribute('type') === Database::VAR_RELATIONSHIP &&
|
||||
$attribute->getAttribute('options')['relationType'] === Database::RELATION_MANY_TO_MANY &&
|
||||
$attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId()
|
||||
) {
|
||||
throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Creating more than one "manyToMany" relationship on the same collection is currently not permitted.');
|
||||
}
|
||||
}
|
||||
|
||||
$attribute = createAttribute(
|
||||
$databaseId,
|
||||
$collectionId,
|
||||
|
||||
@@ -6,6 +6,7 @@ use Tests\E2E\Client;
|
||||
use Tests\E2E\Scopes\Scope;
|
||||
use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\SideClient;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
@@ -317,6 +318,164 @@ class DatabasesCustomClientTest extends Scope
|
||||
$this->assertEquals('restrict', $collection1RelationAttribute['onDelete']);
|
||||
}
|
||||
|
||||
public function testRelationshipSameTwoWayKey(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Same two way key'
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
$collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'c1',
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
]);
|
||||
|
||||
$collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'c2',
|
||||
'documentSecurity' => false,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedCollectionId' => $collection2['body']['$id'],
|
||||
'type' => Database::RELATION_ONE_TO_ONE,
|
||||
'twoWay' => false,
|
||||
'onDelete' => 'cascade',
|
||||
'key' => 'attr1',
|
||||
'twoWayKey' => 'same_key'
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
$this->assertEquals(202, $relation['headers']['status-code']);
|
||||
$this->assertEquals('same_key', $relation['body']['twoWayKey']);
|
||||
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedCollectionId' => $collection2['body']['$id'],
|
||||
'type' => Database::RELATION_ONE_TO_MANY,
|
||||
'twoWay' => false,
|
||||
'onDelete' => 'cascade',
|
||||
'key' => 'attr2',
|
||||
'twoWayKey' => 'same_key'
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
$this->assertEquals(409, $relation['body']['code']);
|
||||
$this->assertEquals('Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.', $relation['body']['message']);
|
||||
|
||||
// twoWayKey is null TwoWayKey is default
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedCollectionId' => $collection2['body']['$id'],
|
||||
'type' => Database::RELATION_ONE_TO_MANY,
|
||||
'twoWay' => false,
|
||||
'onDelete' => 'cascade',
|
||||
'key' => 'attr3',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
$this->assertEquals(202, $relation['headers']['status-code']);
|
||||
$this->assertArrayHasKey('twoWayKey', $relation['body']);
|
||||
|
||||
// twoWayKey is null, TwoWayKey is default, second POST
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedCollectionId' => $collection2['body']['$id'],
|
||||
'type' => Database::RELATION_ONE_TO_MANY,
|
||||
'twoWay' => false,
|
||||
'onDelete' => 'cascade',
|
||||
'key' => 'attr4',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
$this->assertEquals('Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.', $relation['body']['message']);
|
||||
$this->assertEquals(409, $relation['body']['code']);
|
||||
|
||||
// RelationshipManyToMany
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedCollectionId' => $collection2['body']['$id'],
|
||||
'type' => Database::RELATION_MANY_TO_MANY,
|
||||
'twoWay' => true,
|
||||
'onDelete' => 'setNull',
|
||||
'key' => 'songs',
|
||||
'twoWayKey' => 'playlist',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
$this->assertEquals(202, $relation['headers']['status-code']);
|
||||
$this->assertArrayHasKey('twoWayKey', $relation['body']);
|
||||
|
||||
// Second RelationshipManyToMany on Same collections
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'relatedCollectionId' => $collection2['body']['$id'],
|
||||
'type' => Database::RELATION_MANY_TO_MANY,
|
||||
'twoWay' => true,
|
||||
'onDelete' => 'setNull',
|
||||
'key' => 'songs2',
|
||||
'twoWayKey' => 'playlist2',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
$this->assertEquals(409, $relation['body']['code']);
|
||||
$this->assertEquals('Creating more than one "manyToMany" relationship on the same collection is currently not permitted.', $relation['body']['message']);
|
||||
}
|
||||
|
||||
public function testUpdateWithoutRelationPermission(): void
|
||||
{
|
||||
$userId = $this->getUser()['$id'];
|
||||
|
||||
Reference in New Issue
Block a user