From c96f5ea75af3dd137d8077d2d130ca364f591c3f Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 4 Mar 2021 10:28:24 +0100 Subject: [PATCH] cleanup code --- app/controllers/api/health.php | 5 +-- app/realtime.php | 37 ++++++++----------- app/views/install/compose.phtml | 39 ++++++++++++++++++++ src/Appwrite/Event/Realtime.php | 7 +++- src/Appwrite/Realtime/Realtime.php | 11 ++++++ tests/unit/Realtime/RealtimeChannelsTest.php | 2 - tests/unit/Realtime/RealtimeGuestTest.php | 10 ----- 7 files changed, 72 insertions(+), 39 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index c8559278f..4658ac079 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -40,10 +40,7 @@ App::get('/v1/health/realtime') ->inject('response') ->action(function ($response) { /** @var Utopia\Response $response */ - $redis = new Redis(); - $redis->connect('redis', 6379); - - $redis->publish('realtime', 'I\'m a live message'); + // TODO: realtime health $response->json(['status' => 'OK']); }); diff --git a/app/realtime.php b/app/realtime.php index 15b32c1bb..6671568a1 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -27,15 +27,10 @@ use Utopia\Abuse\Adapters\TimeLimit; /** * TODO List * - * - CORS Validation - * - Limit payload size * - JWT Authentication (in path / or in message) * * Protocols Support: * - Websocket support: https://www.swoole.co.uk/docs/modules/swoole-websocket-server - * - MQTT support: https://www.swoole.co.uk/docs/modules/swoole-mqtt-server - * - SSE support: https://github.com/hhxsv5/php-sse - * - Socket.io support: https://github.com/shuixn/socket.io-swoole-server */ ini_set('default_socket_timeout', -1); @@ -44,13 +39,15 @@ Swoole\Runtime::enableCoroutine(SWOOLE_HOOK_ALL); $server = new Server('0.0.0.0', 80); $server->set([ - 'websocket_compression' => true, 'package_max_length' => 64000 // Default maximum Package Size (64kb) ]); $subscriptions = []; $connections = []; +/** + * Create Redis Connection Pool in favor of the default 'cache' register. + */ $register->set('redis', function () { $user = App::getEnv('_APP_REDIS_USER', ''); $pass = App::getEnv('_APP_REDIS_PASS', ''); @@ -106,14 +103,13 @@ $server->on('workerStart', function ($server, $workerId) use (&$subscriptions, & * Supported Resources: * - Collection * - Document - * - Bucket * - File - * - User? / Account? (no permissions) - * - Session? (no permissions) - * - Team? (no permissions) - * - Membership? (no permissions) - * - Function - * - Execution + * - Account + * - Session + * - Team? (not implemented yet) + * - Membership? (not implemented yet) + * - Function? (not available yet) + * - Execution? (not available yet) */ $event = json_decode($payload, true); @@ -157,7 +153,7 @@ $server->on('start', function (Server $server) { }); $server->on('open', function (Server $server, Request $request) use (&$connections, &$subscriptions, &$register) { - Console::info("Connection open (user: {$request->fd}, worker: {$server->getWorkerId()})"); + Console::info("Connection open (user: {$request->fd}, connections: {}, worker: {$server->getWorkerId()})"); $app = new App(''); $connection = $request->fd; @@ -263,9 +259,9 @@ $server->on('open', function (Server $server, Request $request) use (&$connectio } /* - * Validate Client Domain - Check to avoid CSRF attack - * Adding Appwrite API domains to allow XDOMAIN communication - * Skip this check for non-web platforms which are not required to send an origin header + * Validate Client Domain - Check to avoid CSRF attack. + * Adding Appwrite API domains to allow XDOMAIN communication. + * Skip this check for non-web platforms which are not required to send an origin header. */ $origin = $request->getOrigin(); $originValidator = new Origin(\array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', []))); @@ -296,11 +292,8 @@ $server->on('open', function (Server $server, Request $request) use (&$connectio }); $server->on('message', function (Server $server, Frame $frame) { - if ($frame->data === 'reload') { - $server->reload(); - } - - Console::info('Recieved message: ' . $frame->data . ' (user: ' . $frame->fd . ', worker: ' . $server->getWorkerId() . ')'); + $server->push($frame->fd, 'Sending messages is not allowed.'); + $server->close($frame->fd); }); $server->on('close', function (Server $server, int $fd) use (&$connections, &$subscriptions) { diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 1c0c98108..10d9ec86d 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -95,6 +95,45 @@ services: - _APP_FUNCTIONS_MEMORY_SWAP - _APP_FUNCTIONS_ENVS + appwrite-realtime: + entrypoint: realtime + container_name: appwrite-realtime + build: + context: . + restart: unless-stopped + ports: + - 9505:80 + labels: + - "traefik.enable=true" + - "traefik.constraint-label-stack=appwrite" + - "traefik.docker.network=appwrite" + - "traefik.http.services.appwrite_realtime.loadbalancer.server.port=80" + #ws + - traefik.http.routers.appwrite_realtime_ws.entrypoints=appwrite_web + - traefik.http.routers.appwrite_realtime_ws.rule=PathPrefix(`/v1/realtime`) + - traefik.http.routers.appwrite_realtime_ws.service=appwrite_realtime + # wss + - traefik.http.routers.appwrite_realtime_wss.entrypoints=appwrite_websecure + - traefik.http.routers.appwrite_realtime_wss.rule=PathPrefix(`/v1/realtime`) + - traefik.http.routers.appwrite_realtime_wss.service=appwrite_realtime + - traefik.http.routers.appwrite_realtime_wss.tls=true + - traefik.http.routers.appwrite_realtime_wss.tls.certresolver=dns + networks: + - appwrite + depends_on: + - redis + environment: + - _APP_ENV + - _APP_OPTIONS_ABUSE + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + appwrite-worker-usage: image: appwrite/appwrite: entrypoint: worker-usage diff --git a/src/Appwrite/Event/Realtime.php b/src/Appwrite/Event/Realtime.php index cbae7d462..c0f6d2ad3 100644 --- a/src/Appwrite/Event/Realtime.php +++ b/src/Appwrite/Event/Realtime.php @@ -85,7 +85,7 @@ class Realtime /** * @param array $payload - * return $this + * @return $this */ public function setPayload(array $payload): self { @@ -169,6 +169,11 @@ class Realtime $this->reset(); } + /** + * Resets this event and unpopulates all data. + * + * @return $this + */ public function reset(): self { $this->event = ''; diff --git a/src/Appwrite/Realtime/Realtime.php b/src/Appwrite/Realtime/Realtime.php index 256ad64b3..93e5cffd9 100644 --- a/src/Appwrite/Realtime/Realtime.php +++ b/src/Appwrite/Realtime/Realtime.php @@ -13,6 +13,8 @@ class Realtime static $user; /** + * Sets the current user for the role and channel parsing. + * * @param Document $user */ static function setUser(Document $user) @@ -21,10 +23,16 @@ class Realtime } /** + * Returns array of roles that the set User has permissions to. + * * @return array */ static function getRoles() { + if (!isset(self::$user)) { + return []; + } + $roles = ['role:' . ((self::$user->isEmpty()) ? Auth::USER_ROLE_GUEST : Auth::USER_ROLE_MEMBER)]; if (!(self::$user->isEmpty())) { $roles[] = 'user:' . self::$user->getId(); @@ -42,6 +50,9 @@ class Realtime } /** + * Converts the channels from the Query Params into an array. + * Also renames the account channel to account.USER_ID and removes all illegal account channel variations. + * * @param array $channels */ static function parseChannels(array $channels) diff --git a/tests/unit/Realtime/RealtimeChannelsTest.php b/tests/unit/Realtime/RealtimeChannelsTest.php index d5b090395..1853254b4 100644 --- a/tests/unit/Realtime/RealtimeChannelsTest.php +++ b/tests/unit/Realtime/RealtimeChannelsTest.php @@ -32,8 +32,6 @@ class RealtimeChannelsTest extends TestCase 'documents.2', ]; - - public function setUp(): void { /** diff --git a/tests/unit/Realtime/RealtimeGuestTest.php b/tests/unit/Realtime/RealtimeGuestTest.php index 4eff23b1c..b8cd68f8a 100644 --- a/tests/unit/Realtime/RealtimeGuestTest.php +++ b/tests/unit/Realtime/RealtimeGuestTest.php @@ -11,14 +11,6 @@ class RealtimeGuestTest extends TestCase public $connections = []; public $subscriptions = []; - public function setUp(): void - { - } - - public function tearDown(): void - { - } - public function testGuest() { Realtime::setUser(new Document([ @@ -47,7 +39,6 @@ class RealtimeGuestTest extends TestCase Realtime::subscribe('1', 1, $roles, $this->subscriptions, $this->connections, $channels); - $event = [ 'project' => '1', 'permissions' => ['*'], @@ -192,7 +183,6 @@ class RealtimeGuestTest extends TestCase $this->assertCount(1, $this->connections); $this->assertCount(1, $this->subscriptions['1']); - Realtime::unsubscribe(1, $this->subscriptions, $this->connections); $this->assertEmpty($this->connections);