From 1380f0ba0a91f9a83961452293a085da262537ea Mon Sep 17 00:00:00 2001 From: Alex Bouma Date: Tue, 15 Sep 2020 15:55:59 +0200 Subject: [PATCH 1/3] Add failing test --- tests/Channels/PresenceChannelTest.php | 65 ++++++++++++++++++-------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/tests/Channels/PresenceChannelTest.php b/tests/Channels/PresenceChannelTest.php index 1749c13877..26cec744ca 100644 --- a/tests/Channels/PresenceChannelTest.php +++ b/tests/Channels/PresenceChannelTest.php @@ -2,6 +2,7 @@ namespace BeyondCode\LaravelWebSockets\Tests\Channels; +use BeyondCode\LaravelWebSockets\Tests\Mocks\Connection; use BeyondCode\LaravelWebSockets\Tests\Mocks\Message; use BeyondCode\LaravelWebSockets\Tests\TestCase; use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature; @@ -42,16 +43,7 @@ public function clients_with_valid_auth_signatures_can_join_presence_channels() ], ]; - $signature = "{$connection->socketId}:presence-channel:".json_encode($channelData); - - $message = new Message(json_encode([ - 'event' => 'pusher:subscribe', - 'data' => [ - 'auth' => $connection->app->key.':'.hash_hmac('sha256', $signature, $connection->app->secret), - 'channel' => 'presence-channel', - 'channel_data' => json_encode($channelData), - ], - ])); + $message = $this->getSignedMessage($connection, 'presence-channel', $channelData); $this->pusherServer->onMessage($connection, $message); @@ -71,16 +63,7 @@ public function clients_with_no_user_info_can_join_presence_channels() 'user_id' => 1, ]; - $signature = "{$connection->socketId}:presence-channel:".json_encode($channelData); - - $message = new Message(json_encode([ - 'event' => 'pusher:subscribe', - 'data' => [ - 'auth' => $connection->app->key.':'.hash_hmac('sha256', $signature, $connection->app->secret), - 'channel' => 'presence-channel', - 'channel_data' => json_encode($channelData), - ], - ])); + $message = $this->getSignedMessage($connection, 'presence-channel', $channelData); $this->pusherServer->onMessage($connection, $message); @@ -88,4 +71,46 @@ public function clients_with_no_user_info_can_join_presence_channels() 'channel' => 'presence-channel', ]); } + + /** @test */ + public function multiple_clients_with_same_user_id_are_counted_once() + { + $this->pusherServer->onOpen($connection = $this->getWebSocketConnection()); + $this->pusherServer->onOpen($connection2 = $this->getWebSocketConnection()); + + $channelName = 'presence-channel'; + $channelData = [ + 'user_id' => $userId = 1, + ]; + + $this->pusherServer->onMessage($connection, $this->getSignedMessage($connection, $channelName, $channelData)); + $this->pusherServer->onMessage($connection2, $this->getSignedMessage($connection2, $channelName, $channelData)); + + $connection2->assertSentEvent('pusher_internal:subscription_succeeded', [ + 'channel' => $channelName, + 'data' => json_encode([ + 'presence' => [ + 'ids' => [(string)$userId], + 'hash' => [ + (string)$userId => [], + ], + 'count' => 1, + ], + ]), + ]); + } + + private function getSignedMessage(Connection $connection, string $channelName, array $channelData): Message + { + $signature = "{$connection->socketId}:{$channelName}:" . json_encode($channelData); + + return new Message(json_encode([ + 'event' => 'pusher:subscribe', + 'data' => [ + 'auth' => $connection->app->key . ':' . hash_hmac('sha256', $signature, $connection->app->secret), + 'channel' => $channelName, + 'channel_data' => json_encode($channelData), + ], + ])); + } } From 9da68ecd40abb876efb43298ae9d568c2c2734da Mon Sep 17 00:00:00 2001 From: Alex Bouma Date: Tue, 15 Sep 2020 15:57:50 +0200 Subject: [PATCH 2/3] Fix double counting users in presence channel --- src/WebSockets/Channels/PresenceChannel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WebSockets/Channels/PresenceChannel.php b/src/WebSockets/Channels/PresenceChannel.php index 479d365066..a4de1570ce 100644 --- a/src/WebSockets/Channels/PresenceChannel.php +++ b/src/WebSockets/Channels/PresenceChannel.php @@ -63,9 +63,9 @@ protected function getChannelData(): array { return [ 'presence' => [ - 'ids' => $this->getUserIds(), + 'ids' => $userIds = $this->getUserIds(), 'hash' => $this->getHash(), - 'count' => count($this->users), + 'count' => count($userIds), ], ]; } @@ -73,7 +73,7 @@ protected function getChannelData(): array public function toArray(): array { return array_merge(parent::toArray(), [ - 'user_count' => count($this->users), + 'user_count' => count($this->getUserIds()), ]); } @@ -83,7 +83,7 @@ protected function getUserIds(): array return (string) $channelData->user_id; }, $this->users); - return array_values($userIds); + return array_values(array_unique($userIds)); } /** From 5024a2a05aaa6768e8e4a7e381a9563a2f6d76a9 Mon Sep 17 00:00:00 2001 From: Alex Bouma Date: Tue, 15 Sep 2020 16:12:25 +0200 Subject: [PATCH 3/3] CS --- tests/Channels/PresenceChannelTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Channels/PresenceChannelTest.php b/tests/Channels/PresenceChannelTest.php index 26cec744ca..5df163f980 100644 --- a/tests/Channels/PresenceChannelTest.php +++ b/tests/Channels/PresenceChannelTest.php @@ -90,9 +90,9 @@ public function multiple_clients_with_same_user_id_are_counted_once() 'channel' => $channelName, 'data' => json_encode([ 'presence' => [ - 'ids' => [(string)$userId], + 'ids' => [(string) $userId], 'hash' => [ - (string)$userId => [], + (string) $userId => [], ], 'count' => 1, ], @@ -102,12 +102,12 @@ public function multiple_clients_with_same_user_id_are_counted_once() private function getSignedMessage(Connection $connection, string $channelName, array $channelData): Message { - $signature = "{$connection->socketId}:{$channelName}:" . json_encode($channelData); + $signature = "{$connection->socketId}:{$channelName}:".json_encode($channelData); return new Message(json_encode([ 'event' => 'pusher:subscribe', 'data' => [ - 'auth' => $connection->app->key . ':' . hash_hmac('sha256', $signature, $connection->app->secret), + 'auth' => $connection->app->key.':'.hash_hmac('sha256', $signature, $connection->app->secret), 'channel' => $channelName, 'channel_data' => json_encode($channelData), ],