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

[draft] Update the User info in the Presence Channel call #401

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/HttpApi/Controllers/UpdateUserInfoController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace BeyondCode\LaravelWebSockets\HttpApi\Controllers;

use BeyondCode\LaravelWebSockets\WebSockets\Channels\PresenceChannel;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Symfony\Component\HttpKernel\Exception\HttpException;

class UpdateUserInfoController extends Controller
{
public function __invoke(Request $request)
{
$channel = $this->channelManager->find($request->appId, $request->channelName);

if (is_null($channel)) {
throw new HttpException(404, 'Unknown channel "'.$request->channelName.'"');
}

if (! $channel instanceof PresenceChannel) {
throw new HttpException(400, 'Invalid presence channel "'.$request->channelName.'"');
}

$user = Collection::make($channel->getUsers())->filter(function($user) use ($request) {
return $user->user_id === (int) $request->userId;
})->first();

if (is_null($user)) {
throw new HttpException(404, 'Unknown user "'.$request->userId.'"');
}

$channel->updateUserInfo($user->user_id, (object) $request->info);
}
}
2 changes: 2 additions & 0 deletions src/Server/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchChannelsController;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchUsersController;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\TriggerEventController;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\UpdateUserInfoController;
use BeyondCode\LaravelWebSockets\Server\Logger\WebsocketsLogger;
use BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler;
use Illuminate\Support\Collection;
Expand Down Expand Up @@ -40,6 +41,7 @@ public function echo()
$this->get('/apps/{appId}/channels', FetchChannelsController::class);
$this->get('/apps/{appId}/channels/{channelName}', FetchChannelController::class);
$this->get('/apps/{appId}/channels/{channelName}/users', FetchUsersController::class);
$this->put('/apps/{appId}/channels/{channelName}/users/{userId}', UpdateUserInfoController::class);
}

public function customRoutes()
Expand Down
10 changes: 10 additions & 0 deletions src/WebSockets/Channels/PresenceChannel.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ public function getUsers(): array
return $this->users;
}

public function updateUserInfo(int $id, object $info)
{
foreach ($this->users as $key => $user) {
if ($user->user_id === $id) {
$user->user_info = $info;
break;
}
}
}

/*
* @link https://pusher.com/docs/pusher_protocol#presence-channel-events
*/
Expand Down
70 changes: 70 additions & 0 deletions tests/HttpApi/UpdateUserInfoTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace BeyondCode\LaravelWebSockets\Tests\HttpApi;

use BeyondCode\LaravelWebSockets\HttpApi\Controllers\UpdateUserInfoController;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Connection;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use GuzzleHttp\Psr7\Request;
use Illuminate\Http\JsonResponse;
use Pusher\Pusher;
use Symfony\Component\HttpKernel\Exception\HttpException;

class UpdateUserInfoTest extends TestCase
{
/** @test */
public function invalid_signatures_can_not_access_the_api()
{
$this->expectException(HttpException::class);
$this->expectExceptionMessage('Invalid auth signature provided.');

$connection = new Connection();

$requestPath = '/apps/1234/channels/my-channel/users';
$routeParams = [
'appId' => '1234',
'channelName' => 'my-channel',
];

$queryString = Pusher::build_auth_query_string('TestKey', 'InvalidSecret', 'PUT', $requestPath);

$request = new Request('PUT', "{$requestPath}?{$queryString}&".http_build_query($routeParams));

$controller = app(UpdateUserInfoController::class);

$controller->onOpen($connection, $request);
}

/** @test */
public function it_returns_404_for_invalid_channels()
{
$this->expectException(HttpException::class);
$this->expectExceptionMessage('Unknown channel');

$this->getConnectedWebSocketConnection(['my-channel']);

$connection = new Connection();

$requestPath = '/apps/1234/channels/invalid-channel/users';
$routeParams = [
'appId' => '1234',
'channelName' => 'invalid-channel',
];

$queryString = Pusher::build_auth_query_string('TestKey', 'TestSecret', 'PUT', $requestPath);

$request = new Request('PUT', "{$requestPath}?{$queryString}&".http_build_query($routeParams));

$controller = app(UpdateUserInfoController::class);

$controller->onOpen($connection, $request);

/** @var JsonResponse $response */
$response = array_pop($connection->sentRawData);

$this->assertSame([
'occupied' => true,
'subscription_count' => 2,
], json_decode($response->getContent(), true));
}
}