mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge remote-tracking branch 'upstream/1.8.x' into dat-600
This commit is contained in:
commit
7fdbd12937
10 files changed
+867
-7
No files matched your search
@@ -383,6 +383,8 @@ class Event
|
||||
{
|
||||
$this->params = [];
|
||||
$this->sensitive = [];
|
||||
$this->event = '';
|
||||
$this->payload = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
+56
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
@@ -279,4 +280,59 @@ abstract class Action extends UtopiaAction
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* For triggering different queues for each document for a bulk documents
|
||||
* @param string $event
|
||||
* @param Document $database
|
||||
* @param Document $collection
|
||||
* @param Document[] $documents
|
||||
* @param Event $queueForEvents
|
||||
* @param Event $queueForRealtime
|
||||
* @param Event $queueForFunctions
|
||||
* @param Event $queueForWebhooks
|
||||
* @return void
|
||||
*/
|
||||
protected function triggerBulk(
|
||||
string $event,
|
||||
Document $database,
|
||||
Document $collection,
|
||||
array $documents,
|
||||
Event $queueForEvents,
|
||||
Event $queueForRealtime,
|
||||
Event $queueForFunctions,
|
||||
Event $queueForWebhooks
|
||||
): void {
|
||||
$queueForEvents
|
||||
->setEvent($event)
|
||||
->setParam('databaseId', $database->getId())
|
||||
->setContext('database', $database)
|
||||
->setParam('collectionId', $collection->getId())
|
||||
->setParam('tableId', $collection->getId())
|
||||
->setContext($this->getCollectionsEventsContext(), $collection);
|
||||
|
||||
foreach ($documents as $document) {
|
||||
$queueForEvents
|
||||
->setParam('documentId', $document->getId())
|
||||
->setParam('rowId', $document->getId())
|
||||
->setPayload($document->getArrayCopy());
|
||||
|
||||
$queueForRealtime
|
||||
->from($queueForEvents)
|
||||
->trigger();
|
||||
|
||||
$queueForFunctions
|
||||
->from($queueForEvents)
|
||||
->trigger();
|
||||
|
||||
$queueForWebhooks
|
||||
->from($queueForEvents)
|
||||
->trigger();
|
||||
}
|
||||
|
||||
$queueForEvents->reset();
|
||||
$queueForRealtime->reset();
|
||||
$queueForFunctions->reset();
|
||||
$queueForWebhooks->reset();
|
||||
}
|
||||
}
|
||||
+17
-1
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Action;
|
||||
@@ -72,11 +73,15 @@ class Delete extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForRealtime')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForWebhooks')
|
||||
->inject('plan')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, array $plan): void
|
||||
public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void
|
||||
{
|
||||
$database = $dbForProject->getDocument('databases', $databaseId);
|
||||
if ($database->isEmpty()) {
|
||||
@@ -134,5 +139,16 @@ class Delete extends Action
|
||||
'total' => $modified,
|
||||
$this->getSdkGroup() => $documents,
|
||||
]), $this->getResponseModel());
|
||||
|
||||
$this->triggerBulk(
|
||||
'databases.[databaseId].collections.[collectionId].documents.[documentId].delete',
|
||||
$database,
|
||||
$collection,
|
||||
$documents,
|
||||
$queueForEvents,
|
||||
$queueForRealtime,
|
||||
$queueForFunctions,
|
||||
$queueForWebhooks
|
||||
);
|
||||
}
|
||||
}
|
||||
+17
-1
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Action;
|
||||
@@ -76,11 +77,15 @@ class Update extends Action
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForRealtime')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForWebhooks')
|
||||
->inject('plan')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string|array $data, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, array $plan): void
|
||||
public function action(string $databaseId, string $collectionId, string|array $data, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void
|
||||
{
|
||||
$data = \is_string($data)
|
||||
? \json_decode($data, true)
|
||||
@@ -158,5 +163,16 @@ class Update extends Action
|
||||
'total' => $modified,
|
||||
$this->getSdkGroup() => $documents
|
||||
]), $this->getResponseModel());
|
||||
|
||||
$this->triggerBulk(
|
||||
'databases.[databaseId].collections.[collectionId].documents.[documentId].update',
|
||||
$database,
|
||||
$collection,
|
||||
$documents,
|
||||
$queueForEvents,
|
||||
$queueForRealtime,
|
||||
$queueForFunctions,
|
||||
$queueForWebhooks
|
||||
);
|
||||
}
|
||||
}
|
||||
+14
-2
@@ -122,10 +122,12 @@ class Create extends Action
|
||||
->inject('user')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForRealtime')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForWebhooks')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage): void
|
||||
public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks): void
|
||||
{
|
||||
$data = \is_string($data)
|
||||
? \json_decode($data, true)
|
||||
@@ -417,6 +419,16 @@ class Create extends Action
|
||||
$this->getSdkGroup() => $documents
|
||||
]), $this->getBulkResponseModel());
|
||||
|
||||
$this->triggerBulk(
|
||||
'databases.[databaseId].collections.[collectionId].documents.[documentId].create',
|
||||
$database,
|
||||
$collection,
|
||||
$documents,
|
||||
$queueForEvents,
|
||||
$queueForRealtime,
|
||||
$queueForFunctions,
|
||||
$queueForWebhooks
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,10 @@ class Delete extends DocumentsDelete
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForRealtime')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForWebhooks')
|
||||
->inject('plan')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
@@ -61,6 +61,10 @@ class Update extends DocumentsUpdate
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForRealtime')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForWebhooks')
|
||||
->inject('plan')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
@@ -101,6 +101,9 @@ class Create extends DocumentCreate
|
||||
->inject('user')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForRealtime')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForWebhooks')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
@@ -182,9 +182,9 @@ abstract class Scope extends TestCase
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getUser(): array
|
||||
public function getUser(bool $fresh = false): array
|
||||
{
|
||||
if (isset(self::$user[$this->getProject()['$id']])) {
|
||||
if (!$fresh && isset(self::$user[$this->getProject()['$id']])) {
|
||||
return self::$user[$this->getProject()['$id']];
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Tests\E2E\Services\Realtime;
|
||||
|
||||
use CURLFile;
|
||||
use Exception;
|
||||
use Tests\E2E\Client;
|
||||
use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\Scope;
|
||||
@@ -12,6 +13,7 @@ use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use WebSocket\ConnectionException;
|
||||
use WebSocket\TimeoutException;
|
||||
|
||||
class RealtimeCustomClientTest extends Scope
|
||||
{
|
||||
@@ -819,7 +821,6 @@ class RealtimeCustomClientTest extends Scope
|
||||
]);
|
||||
|
||||
$response = json_decode($client->receive(), true);
|
||||
|
||||
$this->assertArrayHasKey('type', $response);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertEquals('event', $response['type']);
|
||||
@@ -898,9 +899,755 @@ class RealtimeCustomClientTest extends Scope
|
||||
$this->assertNotEmpty($response['data']['payload']);
|
||||
$this->assertEquals('Bradley Cooper', $response['data']['payload']['name']);
|
||||
|
||||
// test bulk create
|
||||
$documents = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$actorsId}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documents' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'Robert Downey Jr.',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'Scarlett Johansson',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
// Receive first document event
|
||||
$response = json_decode($client->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertEquals('event', $response['type']);
|
||||
$this->assertNotEmpty($response['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
||||
$this->assertCount(6, $response['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response['data']['payload']['$id']}.create", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.create", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.create", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response['data']['events']);
|
||||
$this->assertContains("databases.*", $response['data']['events']);
|
||||
$this->assertNotEmpty($response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response['data']['payload']);
|
||||
$this->assertArrayHasKey('name', $response['data']['payload']);
|
||||
$this->assertArrayHasKey('$permissions', $response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']['$permissions']);
|
||||
$this->assertContains(Permission::read(Role::any()), $response['data']['payload']['$permissions']);
|
||||
$this->assertContains(Permission::update(Role::any()), $response['data']['payload']['$permissions']);
|
||||
$this->assertContains(Permission::delete(Role::any()), $response['data']['payload']['$permissions']);
|
||||
|
||||
// Receive second document event
|
||||
$response = json_decode($client->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertEquals('event', $response['type']);
|
||||
$this->assertNotEmpty($response['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
||||
$this->assertCount(6, $response['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response['data']['payload']['$id']}.create", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.create", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.create", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response['data']['events']);
|
||||
$this->assertContains("databases.*", $response['data']['events']);
|
||||
$this->assertNotEmpty($response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response['data']['payload']);
|
||||
$this->assertArrayHasKey('name', $response['data']['payload']);
|
||||
$this->assertArrayHasKey('$permissions', $response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']['$permissions']);
|
||||
$this->assertContains(Permission::read(Role::any()), $response['data']['payload']['$permissions']);
|
||||
$this->assertContains(Permission::update(Role::any()), $response['data']['payload']['$permissions']);
|
||||
$this->assertContains(Permission::delete(Role::any()), $response['data']['payload']['$permissions']);
|
||||
|
||||
// test bulk update
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'name' => 'Marvel Hero',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
// Receive first document update event
|
||||
$response = json_decode($client->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertEquals('event', $response['type']);
|
||||
$this->assertNotEmpty($response['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
||||
$this->assertCount(6, $response['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response['data']['payload']['$id']}.update", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.*", $response['data']['events']);
|
||||
$this->assertNotEmpty($response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response['data']['payload']);
|
||||
$this->assertEquals('Marvel Hero', $response['data']['payload']['name']);
|
||||
$this->assertArrayHasKey('$permissions', $response['data']['payload']);
|
||||
|
||||
// Receive second document update event
|
||||
$response = json_decode($client->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertEquals('event', $response['type']);
|
||||
$this->assertNotEmpty($response['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
||||
$this->assertCount(6, $response['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response['data']['payload']['$id']}.update", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.*", $response['data']['events']);
|
||||
$this->assertNotEmpty($response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response['data']['payload']);
|
||||
$this->assertEquals('Marvel Hero', $response['data']['payload']['name']);
|
||||
$this->assertArrayHasKey('$permissions', $response['data']['payload']);
|
||||
|
||||
// Receive third document update event
|
||||
$response = json_decode($client->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertEquals('event', $response['type']);
|
||||
$this->assertNotEmpty($response['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
||||
$this->assertCount(6, $response['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response['data']['payload']['$id']}.update", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response['data']['events']);
|
||||
$this->assertContains("databases.*", $response['data']['events']);
|
||||
$this->assertNotEmpty($response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response['data']['payload']);
|
||||
$this->assertEquals('Marvel Hero', $response['data']['payload']['name']);
|
||||
$this->assertArrayHasKey('$permissions', $response['data']['payload']);
|
||||
|
||||
// Test bulk delete
|
||||
$response = $this->client->call(Client::METHOD_DELETE, "/databases/{$databaseId}/collections/{$actorsId}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
// Receive first document delete event
|
||||
$response = json_decode($client->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertEquals('event', $response['type']);
|
||||
$this->assertNotEmpty($response['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
||||
$this->assertCount(6, $response['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response['data']['payload']['$id']}.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.*", $response['data']['events']);
|
||||
$this->assertNotEmpty($response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response['data']['payload']);
|
||||
$this->assertArrayHasKey('name', $response['data']['payload']);
|
||||
$this->assertArrayHasKey('$permissions', $response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']['$permissions']);
|
||||
|
||||
// Receive second document delete event
|
||||
$response = json_decode($client->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertEquals('event', $response['type']);
|
||||
$this->assertNotEmpty($response['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
||||
$this->assertCount(6, $response['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response['data']['payload']['$id']}.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.*", $response['data']['events']);
|
||||
$this->assertNotEmpty($response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response['data']['payload']);
|
||||
$this->assertArrayHasKey('name', $response['data']['payload']);
|
||||
$this->assertArrayHasKey('$permissions', $response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']['$permissions']);
|
||||
|
||||
// Receive third document delete event
|
||||
$response = json_decode($client->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertEquals('event', $response['type']);
|
||||
$this->assertNotEmpty($response['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response['data']);
|
||||
$this->assertCount(6, $response['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response['data']['payload']['$id']}.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response['data']['events']);
|
||||
$this->assertContains("databases.*", $response['data']['events']);
|
||||
$this->assertNotEmpty($response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response['data']['payload']);
|
||||
$this->assertArrayHasKey('name', $response['data']['payload']);
|
||||
$this->assertArrayHasKey('$permissions', $response['data']['payload']);
|
||||
$this->assertIsArray($response['data']['payload']['$permissions']);
|
||||
|
||||
$client->close();
|
||||
}
|
||||
|
||||
public function testChannelDatabaseBulkOperationMultipleClient()
|
||||
{
|
||||
// user with api key will do operations and other valid users
|
||||
$user1 = $this->getUser(true);
|
||||
$user1Id = $user1['$id'];
|
||||
$session = $user1['session'] ?? '';
|
||||
$projectId = $this->getProject()['$id'];
|
||||
|
||||
$client1 = $this->getWebsocket(['documents', 'collections'], [
|
||||
'origin' => 'http://localhost',
|
||||
'cookie' => 'a_session_' . $projectId . '=' . $session
|
||||
]);
|
||||
|
||||
$response = json_decode($client1->receive(), true);
|
||||
|
||||
$this->assertArrayHasKey('type', $response);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertEquals('connected', $response['type']);
|
||||
$this->assertNotEmpty($response['data']);
|
||||
|
||||
$user2 = $this->getUser(true);
|
||||
$user2Id = $user2['$id'];
|
||||
$session = $user2['session'] ?? '';
|
||||
$projectId = $this->getProject()['$id'];
|
||||
|
||||
$client2 = $this->getWebsocket(['documents', 'collections'], [
|
||||
'origin' => 'http://localhost',
|
||||
'cookie' => 'a_session_' . $projectId . '=' . $session
|
||||
]);
|
||||
|
||||
$response = json_decode($client2->receive(), true);
|
||||
|
||||
$this->assertArrayHasKey('type', $response);
|
||||
$this->assertArrayHasKey('data', $response);
|
||||
$this->assertEquals('connected', $response['type']);
|
||||
$this->assertNotEmpty($response['data']);
|
||||
|
||||
|
||||
/**
|
||||
* Test Database Create
|
||||
*/
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Actors DB',
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
/**
|
||||
* Test Collection Create
|
||||
*/
|
||||
$actors = $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' => 'Actors',
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
'documentSecurity' => true,
|
||||
]);
|
||||
|
||||
$actorsId = $actors['body']['$id'];
|
||||
|
||||
$name = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'name',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $name['headers']['status-code']);
|
||||
$this->assertEquals('name', $name['body']['key']);
|
||||
$this->assertEquals('string', $name['body']['type']);
|
||||
$this->assertEquals(256, $name['body']['size']);
|
||||
$this->assertTrue($name['body']['required']);
|
||||
|
||||
sleep(2);
|
||||
|
||||
// create
|
||||
$this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$actorsId}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documents' => [
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'Any',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'Users',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::users()),
|
||||
Permission::update(Role::users()),
|
||||
Permission::delete(Role::users()),
|
||||
],
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'User1',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($user1Id)),
|
||||
],
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'User2',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($user2Id)),
|
||||
],
|
||||
],
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'name' => 'User2',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($user2Id)),
|
||||
],
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
// Receive and assert for client1 - should receive 3 individual document events
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
$response1 = json_decode($client1->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response1);
|
||||
$this->assertArrayHasKey('data', $response1);
|
||||
$this->assertEquals('event', $response1['type']);
|
||||
$this->assertNotEmpty($response1['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response1['data']);
|
||||
$this->assertCount(6, $response1['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response1['data']['payload']['$id']}.create", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.create", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.create", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response1['data']['events']);
|
||||
$this->assertContains("databases.*", $response1['data']['events']);
|
||||
$this->assertNotEmpty($response1['data']['payload']);
|
||||
$this->assertIsArray($response1['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response1['data']['payload']);
|
||||
$this->assertArrayHasKey('name', $response1['data']['payload']);
|
||||
$this->assertArrayHasKey('$permissions', $response1['data']['payload']);
|
||||
$this->assertIsArray($response1['data']['payload']['$permissions']);
|
||||
}
|
||||
|
||||
// Receive and assert for client2 - should receive 4 individual document events
|
||||
for ($i = 0; $i < 4; $i++) {
|
||||
$response2 = json_decode($client2->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response2);
|
||||
$this->assertArrayHasKey('data', $response2);
|
||||
$this->assertEquals('event', $response2['type']);
|
||||
$this->assertNotEmpty($response2['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response2['data']);
|
||||
$this->assertCount(6, $response2['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response2['data']['payload']['$id']}.create", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.create", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.create", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response2['data']['events']);
|
||||
$this->assertContains("databases.*", $response2['data']['events']);
|
||||
$this->assertNotEmpty($response2['data']['payload']);
|
||||
$this->assertIsArray($response2['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response2['data']['payload']);
|
||||
$this->assertArrayHasKey('name', $response2['data']['payload']);
|
||||
$this->assertArrayHasKey('$permissions', $response2['data']['payload']);
|
||||
$this->assertIsArray($response2['data']['payload']['$permissions']);
|
||||
}
|
||||
|
||||
|
||||
// Perform bulk update(making it only accessible by user1)
|
||||
$response = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$actorsId}/documents/", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'name' => 'Marvel Hero',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($user1Id)),
|
||||
Permission::update(Role::user($user1Id)),
|
||||
Permission::delete(Role::user($user1Id)),
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
// Receive and assert for client1
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$response1 = json_decode($client1->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response1);
|
||||
$this->assertArrayHasKey('data', $response1);
|
||||
$this->assertEquals('event', $response1['type']);
|
||||
$this->assertNotEmpty($response1['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response1['data']);
|
||||
$this->assertCount(6, $response1['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response1['data']['payload']['$id']}.update", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.update", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.update", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response1['data']['events']);
|
||||
$this->assertContains("databases.*", $response1['data']['events']);
|
||||
$this->assertNotEmpty($response1['data']['payload']);
|
||||
$this->assertIsArray($response1['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response1['data']['payload']);
|
||||
$this->assertEquals('Marvel Hero', $response1['data']['payload']['name']);
|
||||
$this->assertArrayHasKey('$permissions', $response1['data']['payload']);
|
||||
}
|
||||
|
||||
// client2 shouldn't receive any event and lead to timeout
|
||||
try {
|
||||
json_decode($client2->receive(), true);
|
||||
$this->fail('Expected TimeoutException was not thrown.');
|
||||
} catch (Exception $e) {
|
||||
$this->assertInstanceOf(TimeoutException::class, $e);
|
||||
}
|
||||
|
||||
// Perform bulk update(making it only accessible by user2)
|
||||
$response = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$actorsId}/documents/", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'name' => 'Marvel Hero',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($user2Id)),
|
||||
Permission::update(Role::user($user2Id)),
|
||||
Permission::delete(Role::user($user2Id)),
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
// Receive and assert for client2
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$response2 = json_decode($client2->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response2);
|
||||
$this->assertArrayHasKey('data', $response2);
|
||||
$this->assertEquals('event', $response2['type']);
|
||||
$this->assertNotEmpty($response2['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response2['data']);
|
||||
$this->assertCount(6, $response2['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response2['data']['payload']['$id']}.update", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.update", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.update", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response2['data']['events']);
|
||||
$this->assertContains("databases.*", $response2['data']['events']);
|
||||
$this->assertNotEmpty($response2['data']['payload']);
|
||||
$this->assertIsArray($response2['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response2['data']['payload']);
|
||||
$this->assertEquals('Marvel Hero', $response2['data']['payload']['name']);
|
||||
$this->assertArrayHasKey('$permissions', $response2['data']['payload']);
|
||||
}
|
||||
|
||||
// client1 shouldn't receive any event and lead to timeout
|
||||
try {
|
||||
json_decode($client1->receive(), true);
|
||||
$this->fail('Expected TimeoutException was not thrown.');
|
||||
} catch (Exception $e) {
|
||||
$this->assertInstanceOf(TimeoutException::class, $e);
|
||||
}
|
||||
|
||||
// Updating the permission for both the users
|
||||
$response = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$actorsId}/documents/", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'name' => 'Marvel Hero',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::users()),
|
||||
Permission::update(Role::users()),
|
||||
Permission::delete(Role::users()),
|
||||
]
|
||||
],
|
||||
]);
|
||||
// both user1 and user2 should receive the event
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$response1 = json_decode($client1->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response1);
|
||||
$this->assertArrayHasKey('data', $response1);
|
||||
$this->assertEquals('event', $response1['type']);
|
||||
$this->assertNotEmpty($response1['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response1['data']);
|
||||
$this->assertCount(6, $response1['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response1['data']['payload']['$id']}.update", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.update", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.update", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response1['data']['events']);
|
||||
$this->assertContains("databases.*", $response1['data']['events']);
|
||||
$this->assertNotEmpty($response1['data']['payload']);
|
||||
$this->assertIsArray($response1['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response1['data']['payload']);
|
||||
$this->assertEquals('Marvel Hero', $response1['data']['payload']['name']);
|
||||
$this->assertArrayHasKey('$permissions', $response1['data']['payload']);
|
||||
|
||||
$response2 = json_decode($client2->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response2);
|
||||
$this->assertArrayHasKey('data', $response2);
|
||||
$this->assertEquals('event', $response2['type']);
|
||||
$this->assertNotEmpty($response2['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response2['data']);
|
||||
$this->assertCount(6, $response2['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response2['data']['payload']['$id']}.update", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.update", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.update", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response2['data']['events']);
|
||||
$this->assertContains("databases.*", $response2['data']['events']);
|
||||
$this->assertNotEmpty($response2['data']['payload']);
|
||||
$this->assertIsArray($response2['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response2['data']['payload']);
|
||||
$this->assertEquals('Marvel Hero', $response2['data']['payload']['name']);
|
||||
$this->assertArrayHasKey('$permissions', $response2['data']['payload']);
|
||||
}
|
||||
|
||||
// Perform bulk delete
|
||||
$response = $this->client->call(Client::METHOD_DELETE, "/databases/{$databaseId}/collections/{$actorsId}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
// Receive and assert for client1
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$response1 = json_decode($client1->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response1);
|
||||
$this->assertArrayHasKey('data', $response1);
|
||||
$this->assertEquals('event', $response1['type']);
|
||||
$this->assertNotEmpty($response1['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response1['data']);
|
||||
$this->assertCount(6, $response1['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response1['data']['payload']['$id']}.delete", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.delete", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.delete", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response1['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response1['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response1['data']['events']);
|
||||
$this->assertContains("databases.*", $response1['data']['events']);
|
||||
$this->assertNotEmpty($response1['data']['payload']);
|
||||
$this->assertIsArray($response1['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response1['data']['payload']);
|
||||
$this->assertArrayHasKey('name', $response1['data']['payload']);
|
||||
$this->assertArrayHasKey('$permissions', $response1['data']['payload']);
|
||||
$this->assertIsArray($response1['data']['payload']['$permissions']);
|
||||
}
|
||||
|
||||
// Receive and assert for client2
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$response2 = json_decode($client2->receive(), true);
|
||||
$this->assertArrayHasKey('type', $response2);
|
||||
$this->assertArrayHasKey('data', $response2);
|
||||
$this->assertEquals('event', $response2['type']);
|
||||
$this->assertNotEmpty($response2['data']);
|
||||
$this->assertArrayHasKey('timestamp', $response2['data']);
|
||||
$this->assertCount(6, $response2['data']['channels']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$response2['data']['payload']['$id']}.delete", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*.delete", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*.delete", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}.documents.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*", $response2['data']['events']);
|
||||
$this->assertContains("databases.*.collections.{$actorsId}", $response2['data']['events']);
|
||||
$this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response2['data']['events']);
|
||||
$this->assertContains("databases.*", $response2['data']['events']);
|
||||
$this->assertNotEmpty($response2['data']['payload']);
|
||||
$this->assertIsArray($response2['data']['payload']);
|
||||
$this->assertArrayHasKey('$id', $response2['data']['payload']);
|
||||
$this->assertArrayHasKey('name', $response2['data']['payload']);
|
||||
$this->assertArrayHasKey('$permissions', $response2['data']['payload']);
|
||||
$this->assertIsArray($response2['data']['payload']['$permissions']);
|
||||
}
|
||||
|
||||
$client1->close();
|
||||
$client2->close();
|
||||
}
|
||||
|
||||
public function testChannelDatabaseCollectionPermissions()
|
||||
{
|
||||
$user = $this->getUser();
|
||||
|
||||
Reference in new issue
Block a user