Merge pull request #527 from stayallive/feature/fix-presence-channels

Fix presence channels double counting users
This commit is contained in:
rennokki 2020-09-15 14:40:31 +00:00 committed by GitHub
commit 2ae00bef84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 24 deletions

View File

@ -63,9 +63,9 @@ class PresenceChannel extends Channel
{
return [
'presence' => [
'ids' => $this->getUserIds(),
'ids' => $userIds = $this->getUserIds(),
'hash' => $this->getHash(),
'count' => count($this->users),
'count' => count($userIds),
],
];
}
@ -73,7 +73,7 @@ class PresenceChannel extends Channel
public function toArray(): array
{
return array_merge(parent::toArray(), [
'user_count' => count($this->users),
'user_count' => count($this->getUserIds()),
]);
}
@ -83,7 +83,7 @@ class PresenceChannel extends Channel
return (string) $channelData->user_id;
}, $this->users);
return array_values($userIds);
return array_values(array_unique($userIds));
}
/**

View File

@ -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 @@ class PresenceChannelTest extends TestCase
],
];
$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 @@ class PresenceChannelTest extends TestCase
'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 @@ class PresenceChannelTest extends TestCase
'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),
],
]));
}
}