Skip to content
This repository was archived by the owner on Feb 7, 2024. It is now read-only.

Commit 2ae00be

Browse files
authored
Merge pull request #527 from stayallive/feature/fix-presence-channels
Fix presence channels double counting users
2 parents 00dd9b0 + 5024a2a commit 2ae00be

File tree

2 files changed

+48
-23
lines changed

2 files changed

+48
-23
lines changed

src/WebSockets/Channels/PresenceChannel.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,17 @@ protected function getChannelData(): array
6363
{
6464
return [
6565
'presence' => [
66-
'ids' => $this->getUserIds(),
66+
'ids' => $userIds = $this->getUserIds(),
6767
'hash' => $this->getHash(),
68-
'count' => count($this->users),
68+
'count' => count($userIds),
6969
],
7070
];
7171
}
7272

7373
public function toArray(): array
7474
{
7575
return array_merge(parent::toArray(), [
76-
'user_count' => count($this->users),
76+
'user_count' => count($this->getUserIds()),
7777
]);
7878
}
7979

@@ -83,7 +83,7 @@ protected function getUserIds(): array
8383
return (string) $channelData->user_id;
8484
}, $this->users);
8585

86-
return array_values($userIds);
86+
return array_values(array_unique($userIds));
8787
}
8888

8989
/**

tests/Channels/PresenceChannelTest.php

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace BeyondCode\LaravelWebSockets\Tests\Channels;
44

5+
use BeyondCode\LaravelWebSockets\Tests\Mocks\Connection;
56
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
67
use BeyondCode\LaravelWebSockets\Tests\TestCase;
78
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature;
@@ -42,16 +43,7 @@ public function clients_with_valid_auth_signatures_can_join_presence_channels()
4243
],
4344
];
4445

45-
$signature = "{$connection->socketId}:presence-channel:".json_encode($channelData);
46-
47-
$message = new Message(json_encode([
48-
'event' => 'pusher:subscribe',
49-
'data' => [
50-
'auth' => $connection->app->key.':'.hash_hmac('sha256', $signature, $connection->app->secret),
51-
'channel' => 'presence-channel',
52-
'channel_data' => json_encode($channelData),
53-
],
54-
]));
46+
$message = $this->getSignedMessage($connection, 'presence-channel', $channelData);
5547

5648
$this->pusherServer->onMessage($connection, $message);
5749

@@ -71,21 +63,54 @@ public function clients_with_no_user_info_can_join_presence_channels()
7163
'user_id' => 1,
7264
];
7365

74-
$signature = "{$connection->socketId}:presence-channel:".json_encode($channelData);
66+
$message = $this->getSignedMessage($connection, 'presence-channel', $channelData);
7567

76-
$message = new Message(json_encode([
68+
$this->pusherServer->onMessage($connection, $message);
69+
70+
$connection->assertSentEvent('pusher_internal:subscription_succeeded', [
71+
'channel' => 'presence-channel',
72+
]);
73+
}
74+
75+
/** @test */
76+
public function multiple_clients_with_same_user_id_are_counted_once()
77+
{
78+
$this->pusherServer->onOpen($connection = $this->getWebSocketConnection());
79+
$this->pusherServer->onOpen($connection2 = $this->getWebSocketConnection());
80+
81+
$channelName = 'presence-channel';
82+
$channelData = [
83+
'user_id' => $userId = 1,
84+
];
85+
86+
$this->pusherServer->onMessage($connection, $this->getSignedMessage($connection, $channelName, $channelData));
87+
$this->pusherServer->onMessage($connection2, $this->getSignedMessage($connection2, $channelName, $channelData));
88+
89+
$connection2->assertSentEvent('pusher_internal:subscription_succeeded', [
90+
'channel' => $channelName,
91+
'data' => json_encode([
92+
'presence' => [
93+
'ids' => [(string) $userId],
94+
'hash' => [
95+
(string) $userId => [],
96+
],
97+
'count' => 1,
98+
],
99+
]),
100+
]);
101+
}
102+
103+
private function getSignedMessage(Connection $connection, string $channelName, array $channelData): Message
104+
{
105+
$signature = "{$connection->socketId}:{$channelName}:".json_encode($channelData);
106+
107+
return new Message(json_encode([
77108
'event' => 'pusher:subscribe',
78109
'data' => [
79110
'auth' => $connection->app->key.':'.hash_hmac('sha256', $signature, $connection->app->secret),
80-
'channel' => 'presence-channel',
111+
'channel' => $channelName,
81112
'channel_data' => json_encode($channelData),
82113
],
83114
]));
84-
85-
$this->pusherServer->onMessage($connection, $message);
86-
87-
$connection->assertSentEvent('pusher_internal:subscription_succeeded', [
88-
'channel' => 'presence-channel',
89-
]);
90115
}
91116
}

0 commit comments

Comments
 (0)