1
0
Fork 0
mirror of synced 2024-07-03 05:31:38 +12:00

add channels to realtime response

This commit is contained in:
Torsten Dittmann 2021-02-25 11:43:39 +01:00
parent 8869fac629
commit a70cb90be1
2 changed files with 43 additions and 35 deletions

View file

@ -19,10 +19,7 @@ use Utopia\CLI\Console;
use Utopia\Config\Config; use Utopia\Config\Config;
use Utopia\Registry\Registry; use Utopia\Registry\Registry;
use Utopia\Swoole\Request as SwooleRequest; use Utopia\Swoole\Request as SwooleRequest;
use PDO as PDONative; use PDO as PDONative;
use Swoole\Database\RedisConfig;
use Swoole\Database\RedisPool;
/** /**
* TODO List * TODO List
@ -114,9 +111,7 @@ $server->on("workerStart", function ($server, $workerId) use (&$subscriptions, &
Console::error('Pub/sub failed (worker: ' . $workerId . ')'); Console::error('Pub/sub failed (worker: ' . $workerId . ')');
} }
$redis->subscribe(['realtime'], function ($redis, $channel, $payload) use ($server, $workerId, &$connections, &$subscriptions) { $redis->subscribe(['realtime'], function ($redis, $channel, $payload) use ($server, &$connections, &$subscriptions) {
// TODO get project and resource ID and itterate over the resource read(?) permissions and send a message to all listeners
/** /**
* Supported Resources: * Supported Resources:
* - Collection * - Collection
@ -130,20 +125,22 @@ $server->on("workerStart", function ($server, $workerId) use (&$subscriptions, &
* - Function * - Function
* - Execution * - Execution
*/ */
$event = json_decode($payload); $event = json_decode($payload, true);
$receivers = []; $receivers = [];
foreach ($connections as $fd => $connection) { foreach ($connections as $fd => $connection) {
if ($connection['projectId'] !== $event->project) { if ($connection['projectId'] !== $event['project']) {
continue; continue;
} }
foreach ($connection['roles'] as $role) { foreach ($connection['roles'] as $role) {
if (\array_key_exists($role, $subscriptions[$event->project])) { if (\array_key_exists($role, $subscriptions[$event['project']])) {
foreach ($event->channels as $channel) { foreach ($event['data']['channels'] as $channel) {
if (\array_key_exists($channel, $subscriptions[$event->project][$role]) && \in_array($role, $event->permissions)) { if (\array_key_exists($channel, $subscriptions[$event['project']][$role]) && \in_array($role, $event['permissions'])) {
$receivers = array_merge($receivers, array_keys($subscriptions[$event->project][$role][$channel])); foreach (array_keys($subscriptions[$event['project']][$role][$channel]) as $ids) {
$receivers[] = $ids;
}
break; break;
} }
} }
@ -154,13 +151,14 @@ $server->on("workerStart", function ($server, $workerId) use (&$subscriptions, &
$receivers = array_keys(array_flip($receivers)); $receivers = array_keys(array_flip($receivers));
foreach ($receivers as $receiver) { foreach ($receivers as $receiver) {
if ($server->exist($receiver) if ($server->exist($receiver) && $server->isEstablished($receiver)) {
&& $server->isEstablished($receiver) $server->push(
) { $receiver,
$server->push($receiver, json_encode($event->data), SWOOLE_WEBSOCKET_OPCODE_TEXT, json_encode($event['data']),
SWOOLE_WEBSOCKET_FLAG_FIN | SWOOLE_WEBSOCKET_FLAG_COMPRESS); SWOOLE_WEBSOCKET_OPCODE_TEXT,
} SWOOLE_WEBSOCKET_FLAG_FIN | SWOOLE_WEBSOCKET_FLAG_COMPRESS
else { );
} else {
$server->close($receiver); $server->close($receiver);
} }
} }
@ -254,13 +252,26 @@ $server->on('open', function (Server $server, Request $request) use (&$connectio
return $user; return $user;
}, ['project', 'request', 'projectDB']); }, ['project', 'request', 'projectDB']);
$channels = array_flip($request->getQuery('channels', []));
$user = $app->getResource('user');
$project = $app->getResource('project');
$roles = ['*', 'user:' . $user->getId(), 'role:' . (($user->isEmpty()) ? Auth::USER_ROLE_GUEST : Auth::USER_ROLE_MEMBER)];
/** @var Appwrite\Database\Document $user */ /** @var Appwrite\Database\Document $user */
$user = $app->getResource('user');
/** @var Appwrite\Database\Document $project */ /** @var Appwrite\Database\Document $project */
$project = $app->getResource('project');
$channels = $request->getQuery('channels', []);
if (empty($project->getId())) {
$server->push($connection, 'Missing or unknown project ID');
$server->close($connection);
}
if (empty($request->getQuery('channels', []))) {
$server->push($connection, 'Missing or unknown channels');
$server->close($connection);
}
$roles = ['*', 'user:' . $user->getId(), 'role:' . (($user->isEmpty()) ? Auth::USER_ROLE_GUEST : Auth::USER_ROLE_MEMBER)];
$channels = array_flip($channels);
\array_map(function ($node) use (&$roles) { \array_map(function ($node) use (&$roles) {
if (isset($node['teamId']) && isset($node['roles'])) { if (isset($node['teamId']) && isset($node['roles'])) {
@ -304,11 +315,9 @@ $server->on('open', function (Server $server, Request $request) use (&$connectio
'projectId' => $project->getId(), 'projectId' => $project->getId(),
'roles' => $roles, 'roles' => $roles,
]; ];
$server->push($connection, json_encode($subscriptions));
}); });
$server->on('message', function (Server $server, Frame $frame) use (&$connections, &$subscriptions) { $server->on('message', function (Server $server, Frame $frame) {
if ($frame->data === 'reload') { if ($frame->data === 'reload') {
$server->reload(); $server->reload();
} }
@ -341,7 +350,6 @@ $server->on('close', function (Server $server, int $fd) use (&$connections, &$su
unset($connections[$fd]); unset($connections[$fd]);
Console::info('Connection close: ' . $fd); Console::info('Connection close: ' . $fd);
}); });
$server->start(); $server->start();

View file

@ -141,10 +141,10 @@ class Realtime
$redis->connect(App::getEnv('_APP_REDIS_HOST', ''), App::getEnv('_APP_REDIS_PORT', '')); $redis->connect(App::getEnv('_APP_REDIS_HOST', ''), App::getEnv('_APP_REDIS_PORT', ''));
$redis->publish('realtime', json_encode([ $redis->publish('realtime', json_encode([
'project' => $this->project, 'project' => $this->project,
'channels' => $this->channels,
'permissions' => $this->payload->getAttribute('$permissions.read'), 'permissions' => $this->payload->getAttribute('$permissions.read'),
'data' => [ 'data' => [
'event' => $this->event, 'event' => $this->event,
'channels' => $this->channels,
'timestamp' => time(), 'timestamp' => time(),
'payload' => $this->payload->getArrayCopy() 'payload' => $this->payload->getArrayCopy()
] ]