diff --git a/app/realtime.php b/app/realtime.php index 22efe787e8..c574fda0f1 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -8,6 +8,7 @@ use Appwrite\Database\Validator\Authorization; use Appwrite\Event\Event; use Appwrite\Messaging\Adapter\Realtime; use Appwrite\Network\Validator\Origin; +use Appwrite\Utopia\Response; use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; use Swoole\Runtime; @@ -19,7 +20,6 @@ use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Swoole\Request; -use Utopia\Swoole\Response; use Utopia\WebSocket\Server; use Utopia\WebSocket\Adapter; @@ -331,6 +331,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $register, $stats, &$realtime) { $app = new App('UTC'); $request = new Request($request); + $response = new Response(new SwooleResponse()); /** @var PDO $db */ $db = $register->get('dbPool')->get(); @@ -351,8 +352,8 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, return $request; }); - App::setResource('response', function () { - return new Response(new SwooleResponse()); + App::setResource('response', function () use ($response) { + return $response; }); try { @@ -414,7 +415,15 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $realtime->subscribe($project->getId(), $connection, $roles, $channels); - $server->send([$connection], json_encode($channels)); + $user = empty($user->getId()) ? null : $response->output($user, Response::MODEL_USER); + + $server->send([$connection], json_encode([ + 'type' => 'connected', + 'data' => [ + 'channels' => array_keys($channels), + 'user' => $user + ] + ])); $stats->set($project->getId(), [ 'projectId' => $project->getId(), @@ -454,6 +463,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) { try { + $response = new Response(new SwooleResponse()); $db = $register->get('dbPool')->get(); $cache = $register->get('redisPool')->get(); @@ -510,11 +520,13 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re $channels = Realtime::convertChannels(array_flip($realtime->connections[$connection]['channels']), $user->getId()); $realtime->subscribe($realtime->connections[$connection]['projectId'], $connection, $roles, $channels); + $user = $response->output($user, Response::MODEL_USER); $server->send([$connection], json_encode([ 'type' => 'response', 'data' => [ 'to' => 'authentication', - 'success' => true + 'success' => true, + 'user' => $user ] ])); diff --git a/tests/e2e/Services/Realtime/RealtimeBase.php b/tests/e2e/Services/Realtime/RealtimeBase.php index 3716e38ff1..50c0041008 100644 --- a/tests/e2e/Services/Realtime/RealtimeBase.php +++ b/tests/e2e/Services/Realtime/RealtimeBase.php @@ -32,9 +32,7 @@ trait RealtimeBase * Test for SUCCESS */ $client = $this->getWebsocket(['documents']); - $this->assertEquals(json_encode([ - 'documents' => 0 - ]), $client->receive()); + $this->assertNotEmpty($client->receive()); $client->close(); /** @@ -103,25 +101,49 @@ trait RealtimeBase 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session ]; - $client = $this->getWebsocket(['documents']); + $client = $this->getWebsocket(['documents'], $headers); $response = json_decode($client->receive(), true); - $this->assertCount(1, $response); - $this->assertArrayHasKey('documents', $response); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertNotEmpty($response['data']['user']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertEquals($userId, $response['data']['user']['$id']); + $client->close(); $client = $this->getWebsocket(['account'], $headers); $response = json_decode($client->receive(), true); - $this->assertCount(2, $response); - $this->assertArrayHasKey('account', $response); - $this->assertArrayHasKey('account.' . $userId, $response); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertNotEmpty($response['data']['user']); + $this->assertCount(2, $response['data']['channels']); + $this->assertContains('account', $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertEquals($userId, $response['data']['user']['$id']); + $client->close(); $client = $this->getWebsocket(['account', 'documents', 'account.123'], $headers); $response = json_decode($client->receive(), true); - $this->assertCount(3, $response); - $this->assertArrayHasKey('documents', $response); - $this->assertArrayHasKey('account', $response); - $this->assertArrayHasKey('account.' . $userId, $response); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertNotEmpty($response['data']['user']); + $this->assertCount(3, $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains('account', $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertEquals($userId, $response['data']['user']['$id']); + $client->close(); $client = $this->getWebsocket([ @@ -140,19 +162,26 @@ trait RealtimeBase $response = json_decode($client->receive(), true); - $this->assertCount(12, $response); - $this->assertArrayHasKey('account', $response); - $this->assertArrayHasKey('account.' . $userId, $response); - $this->assertArrayHasKey('files', $response); - $this->assertArrayHasKey('files.1', $response); - $this->assertArrayHasKey('collections', $response); - $this->assertArrayHasKey('collections.1', $response); - $this->assertArrayHasKey('collections.1.documents', $response); - $this->assertArrayHasKey('collections.2', $response); - $this->assertArrayHasKey('collections.2.documents', $response); - $this->assertArrayHasKey('documents', $response); - $this->assertArrayHasKey('documents.1', $response); - $this->assertArrayHasKey('documents.2', $response); + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertNotEmpty($response['data']['user']); + $this->assertCount(12, $response['data']['channels']); + $this->assertContains('account', $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); + $this->assertContains('files', $response['data']['channels']); + $this->assertContains('files.1', $response['data']['channels']); + $this->assertContains('collections', $response['data']['channels']); + $this->assertContains('collections.1', $response['data']['channels']); + $this->assertContains('collections.1.documents', $response['data']['channels']); + $this->assertContains('collections.2', $response['data']['channels']); + $this->assertContains('collections.2.documents', $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains('documents.1', $response['data']['channels']); + $this->assertContains('documents.2', $response['data']['channels']); + $this->assertEquals($userId, $response['data']['user']['$id']); + $client->close(); } @@ -168,8 +197,12 @@ trait RealtimeBase ]); $response = json_decode($client->receive(), true); - $this->assertCount(1, $response); - $this->assertArrayHasKey('account', $response); + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('account', $response['data']['channels']); $client->send(\json_encode([ 'type' => 'authentication', @@ -203,10 +236,13 @@ trait RealtimeBase ]); $response = json_decode($client->receive(), true); - $this->assertCount(2, $response); - $this->assertArrayHasKey('account', $response); - $this->assertArrayHasKey('account.' . $userId, $response); - + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(2, $response['data']['channels']); + $this->assertContains('account', $response['data']['channels']); + $this->assertContains('account.' . $userId, $response['data']['channels']); /** * Test Account Name Event */ @@ -489,11 +525,16 @@ trait RealtimeBase 'origin' => 'http://localhost', 'cookie' => 'a_session_'.$projectId.'=' . $session ]); + $response = json_decode($client->receive(), true); - $this->assertCount(2, $response); - $this->assertArrayHasKey('documents', $response); - $this->assertArrayHasKey('collections', $response); + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(2, $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains('collections', $response['data']['channels']); /** * Test Collection Create @@ -655,8 +696,13 @@ trait RealtimeBase 'cookie' => 'a_session_'.$projectId.'=' . $session ]); $response = json_decode($client->receive(), true); - $this->assertCount(1, $response); - $this->assertArrayHasKey('files', $response); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('files', $response['data']['channels']); /** * Test File Create @@ -744,9 +790,15 @@ trait RealtimeBase 'origin' => 'http://localhost', 'cookie' => 'a_session_'.$projectId.'=' . $session ]); + $response = json_decode($client->receive(), true); - $this->assertCount(1, $response); - $this->assertArrayHasKey('executions', $response); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('executions', $response['data']['channels']); /** * Test File Create @@ -843,8 +895,12 @@ trait RealtimeBase $response = json_decode($client->receive(), true); - $this->assertCount(1, $response); - $this->assertArrayHasKey('teams', $response); + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('teams', $response['data']['channels']); /** * Test Team Create @@ -923,8 +979,12 @@ trait RealtimeBase $response = json_decode($client->receive(), true); - $this->assertCount(1, $response); - $this->assertArrayHasKey('memberships', $response); + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('memberships', $response['data']['channels']); $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamId.'/memberships', array_merge([ 'content-type' => 'application/json',