Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
joedixon committed Nov 17, 2023
1 parent 20e75ca commit 8e01699
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 12 deletions.
12 changes: 11 additions & 1 deletion src/Pusher/Http/Controllers/ChannelsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Laravel\Reverb\Pusher\Http\Controllers;

use Illuminate\Support\Str;
use Laravel\Reverb\Http\Connection;
use Psr\Http\Message\RequestInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
Expand All @@ -14,7 +15,16 @@ class ChannelsController extends Controller
*/
public function handle(RequestInterface $request, Connection $connection, ...$args): Response
{
$channels = $this->channels->channels()->mapWithKeys(fn ($connections, $name) => [$name => ['user_count' => count($connections)]]);
$channels = $this->channels->channels();
$info = explode(',', $this->query['info'] ?? '');

if (isset($this->query['filter_by_prefix'])) {
$channels = $channels->filter(fn ($connections, $name) => Str::startsWith($name, $this->query['filter_by_prefix']));
}

$channels = $channels->mapWithKeys(function ($connections, $name) use ($info) {
return [$name => array_filter(['user_count' => in_array('user_count', $info) ? count($connections) : null])];
});

return new JsonResponse((object) ['channels' => $channels]);
}
Expand Down
12 changes: 7 additions & 5 deletions src/Pusher/Http/Controllers/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ abstract class Controller

protected $body;

protected $query;

public function __invoke(RequestInterface $request, Connection $connection, ...$args)
{
parse_str($request->getUri()->getQuery(), $query);
$this->body = $request->getBody()->getContents();
$this->query = $query;

try {
$this->setApplication($args['appId'] ?? null);
Expand Down Expand Up @@ -91,9 +95,7 @@ protected function setChannels()
*/
protected function verifySignature(RequestInterface $request): void
{
parse_str($request->getUri()->getQuery(), $queryParams);

$params = Arr::except($queryParams, [
$params = Arr::except($this->query, [
'auth_signature', 'body_md5', 'appId', 'appKey', 'channelName',
]);

Expand All @@ -111,8 +113,8 @@ protected function verifySignature(RequestInterface $request): void

$signature = hash_hmac('sha256', $signature, $this->application->secret());

if ($signature !== $queryParams['auth_signature']) {
// throw new HttpException(401, 'Authentication signature invalid.');
if ($signature !== $this->query['auth_signature']) {
throw new HttpException(401, 'Authentication signature invalid.');
}
}

Expand Down
17 changes: 17 additions & 0 deletions tests/Feature/Ratchet/ChannelsControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

use Laravel\Reverb\Tests\RatchetTestCase;

use function React\Async\await;

uses(RatchetTestCase::class);

it('can return all channel information', function () {
$this->subscribe('test-channel-one');
$this->subscribe('test-channel-two');

$response = await($this->getWithSignature('channels?info=user_count'));

$this->assertSame(200, $response->getStatusCode());
$this->assertSame('{"channels":{"test-channel-one":{"user_count":1},"test-channel-two":{"user_count":1}}}', $response->getBody()->getContents());
});
36 changes: 30 additions & 6 deletions tests/RatchetTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,17 @@ public function triggerEvent(string $channel, string $event, array $data = []):
$this->assertSame('{}', $response->getBody()->getContents());
}

public function request(string $path, string $method = 'GET', mixed $data = '', string $host = '0.0.0.0', string $port = '8080', string $appId = '123456'): PromiseInterface
{
return (new Browser($this->loop))
->request(
$method,
"http://{$host}:{$port}/apps/{$appId}/{$path}",
[],
($data) ? json_encode($data) : ''
);
}

/**
* Post a request to the server.
*/
Expand All @@ -284,12 +295,7 @@ public function postToServer(
string $port = '8080',
string $appId = '123456'
): PromiseInterface {
return (new Browser($this->loop))
->post(
"http://{$host}:{$port}/apps/{$appId}/{$path}",
[],
json_encode($data)
);
return $this->request($path, 'POST', $data, $host, $port, $appId);
}

/**
Expand All @@ -310,4 +316,22 @@ public function postToServerWithSignature(

return $this->postToServer("{$path}?{$query}&auth_signature={$signature}", $data, $host, $port, $appId);
}

public function getWithSignature(
string $path,
array $data = [],
string $host = '0.0.0.0',
string $port = '8080',
string $appId = '123456'
): PromiseInterface {
$hash = md5(json_encode($data));
$timestamp = time();
$query = "auth_key=pusher-key&auth_timestamp={$timestamp}&auth_version=1.0&body_md5={$hash}";
$string = "POST\n/apps/{$appId}/{$path}\n$query";
$signature = hash_hmac('sha256', $string, 'pusher-secret');

$path = Str::contains($path, '?') ? "{$path}&{$query}" : "{$path}?{$query}";

return $this->request("{$path}&auth_signature={$signature}", 'GET', '', $host, $port, $appId);
}
}

0 comments on commit 8e01699

Please sign in to comment.