diff --git a/app/realtime.php b/app/realtime.php index 2c7d9f1ae..2fa34fec7 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -241,8 +241,6 @@ $server->on('open', function (Server $server, Request $request) use (&$connectio /** @var Appwrite\Database\Document $project */ $project = $app->getResource('project'); - $channels = $request->getQuery('channels', []); - /* * Abuse Check */ @@ -271,52 +269,18 @@ $server->on('open', function (Server $server, Request $request) use (&$connectio Realtime::setUser($user); - $roles = ['*', 'user:' . $user->getId(), 'role:' . (($user->isEmpty()) ? Auth::USER_ROLE_GUEST : Auth::USER_ROLE_MEMBER)]; - $channels = array_flip($channels); - - Realtime::parseChannels($channels); - Realtime::parseRoles($roles); + $roles = Realtime::getRoles(); + $channels = Realtime::parseChannels($request->getQuery('channels', [])); /** * Channels Check */ - if (empty($request->getQuery('channels', []))) { + if (empty($channels)) { $server->push($connection, 'Missing channels'); $server->close($connection); } - - /** - * Build Subscriptions Tree - * - * [PROJECT_ID] -> - * [ROLE_X] -> - * [CHANNEL_NAME_X] -> [CONNECTION_ID] - * [CHANNEL_NAME_Y] -> [CONNECTION_ID] - * [CHANNEL_NAME_Z] -> [CONNECTION_ID] - * [ROLE_Y] -> - * [CHANNEL_NAME_X] -> [CONNECTION_ID] - * [CHANNEL_NAME_Y] -> [CONNECTION_ID] - * [CHANNEL_NAME_Z] -> [CONNECTION_ID] - */ - - if (!isset($subscriptions[$project->getId()])) { // Init Project - $subscriptions[$project->getId()] = []; - } - - foreach ($roles as $key => $role) { - if (!isset($subscriptions[$project->getId()][$role])) { // Add user first connection - $subscriptions[$project->getId()][$role] = []; - } - - foreach ($channels as $channel => $list) { - $subscriptions[$project->getId()][$role][$channel][$connection] = true; - } - } - - $connections[$connection] = [ - 'projectId' => $project->getId(), - 'roles' => $roles, - ]; + + Realtime::addSubscription($project->getId(), $connection, $subscriptions, $connections, $roles, $channels); $server->push($connection, json_encode($channels)); }); @@ -330,6 +294,9 @@ $server->on('message', function (Server $server, Frame $frame) { }); $server->on('close', function (Server $server, int $fd) use (&$connections, &$subscriptions) { + /** + * TODO: Move into Realtime Class for tests + */ $projectId = $connections[$fd]['projectId'] ?? ''; $roles = $connections[$fd]['roles'] ?? []; diff --git a/src/Appwrite/Realtime/Realtime.php b/src/Appwrite/Realtime/Realtime.php index 5166f4bff..b6028baf4 100644 --- a/src/Appwrite/Realtime/Realtime.php +++ b/src/Appwrite/Realtime/Realtime.php @@ -2,6 +2,7 @@ namespace Appwrite\Realtime; +use Appwrite\Auth\Auth; use Appwrite\Database\Document; class Realtime @@ -19,11 +20,34 @@ class Realtime self::$user = $user; } + /** + * @return array + */ + static function getRoles() + { + $roles = ['*', 'role:' . ((self::$user->isEmpty()) ? Auth::USER_ROLE_GUEST : Auth::USER_ROLE_MEMBER)]; + if (!(self::$user->isEmpty())) { + $roles[] = 'user:' . self::$user->getId(); + } + foreach (self::$user->getAttribute('memberships', []) as $node) { + if (isset($node['teamId']) && isset($node['roles'])) { + $roles[] = 'team:' . $node['teamId']; + + foreach ($node['roles'] as $nodeRole) { // Set all team roles + $roles[] = 'team:' . $node['teamId'] . '/' . $nodeRole; + } + } + } + return $roles; + } + /** * @param array $channels */ - static function parseChannels(array &$channels) + static function parseChannels(array $channels) { + $channels = array_flip($channels); + foreach ($channels as $key => $value) { if (strpos($key, 'account.') === 0) { unset($channels[$key]); @@ -41,22 +65,8 @@ class Realtime } unset($channels['account']); } - } - /** - * @param array $roles - */ - static function parseRoles(array &$roles) - { - \array_map(function ($node) use (&$roles) { - if (isset($node['teamId']) && isset($node['roles'])) { - $roles[] = 'team:' . $node['teamId']; - - foreach ($node['roles'] as $nodeRole) { // Set all team roles - $roles[] = 'team:' . $node['teamId'] . '/' . $nodeRole; - } - } - }, self::$user->getAttribute('memberships', [])); + return $channels; } /** @@ -90,4 +100,49 @@ class Realtime return array_keys(array_flip($receivers)); } + + /** + * Adds Subscription. + * + * @param string $projectId + * @param mixed $connection + * @param array $subscriptions + * @param array $roles + * @param array $channels + */ + static function addSubscription($projectId, $connection, &$subscriptions, &$connections, &$roles, &$channels) + { + /** + * Build Subscriptions Tree + * + * [PROJECT_ID] -> + * [ROLE_X] -> + * [CHANNEL_NAME_X] -> [CONNECTION_ID] + * [CHANNEL_NAME_Y] -> [CONNECTION_ID] + * [CHANNEL_NAME_Z] -> [CONNECTION_ID] + * [ROLE_Y] -> + * [CHANNEL_NAME_X] -> [CONNECTION_ID] + * [CHANNEL_NAME_Y] -> [CONNECTION_ID] + * [CHANNEL_NAME_Z] -> [CONNECTION_ID] + */ + + if (!isset($subscriptions[$projectId])) { // Init Project + $subscriptions[$projectId] = []; + } + + foreach ($roles as $key => $role) { + if (!isset($subscriptions[$projectId][$role])) { // Add user first connection + $subscriptions[$projectId][$role] = []; + } + + foreach ($channels as $channel => $list) { + $subscriptions[$projectId][$role][$channel][$connection] = true; + } + } + + $connections[$connection] = [ + 'projectId' => $projectId, + 'roles' => $roles, + ]; + } }