From bc5320224e0e5858d2c3245ee3bcbf0b6e512510 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andrej=20Rama=C5=A1euski?= <andrej@x2.cz>
Date: Sun, 3 Jan 2021 01:00:46 +0100
Subject: [PATCH] Lepsi pocitani, prepnuti na Mojo::Pg

---
 lib/CF/Controller/Websockets.pm | 68 ++++++++++++++++++++++-----------
 1 file changed, 45 insertions(+), 23 deletions(-)

diff --git a/lib/CF/Controller/Websockets.pm b/lib/CF/Controller/Websockets.pm
index c2329a2..a1772d4 100644
--- a/lib/CF/Controller/Websockets.pm
+++ b/lib/CF/Controller/Websockets.pm
@@ -8,13 +8,12 @@ use POSIX qw(ceil);
 use feature 'signatures';
 no warnings qw{ experimental::signatures };
 
-use constant SOCKET_INACTIVITY_TIMEOUT => 300;
+use constant SOCKET_INACTIVITY_TIMEOUT => 180;
 
 sub main {
     my $c  = shift;
-    my $ip = $c->tx->remote_address;
-
-    my $user;
+    my $ip  = $c->tx->remote_address;
+    my $key = $c->req->headers->header('Sec-WebSocket-Key');
 
     $c->inactivity_timeout(SOCKET_INACTIVITY_TIMEOUT);
 
@@ -25,29 +24,53 @@ sub main {
     });
 
     $c->on(json => sub( $c, $message ) {
-
         if ( $message->{event} eq 'KEEPALIVE' ) {
 
-            if ($message->{payload} =~ /^(\d+)$/) {
-                # TODO: check signtaure
+            my $user;
+
+            if ($message->{payload} =~ /^\d+$/) {
+
+                $user = $c->pg->db->select('users',
+                    [qw(id username secret jitsi_allowed roles banned_until)],
+                    { id => $message->{payload}}
+                )->hash;
+            }
 
-                $user //= $c->schema->resultset('User')->find(
-                    { id => $1 }
-                );
+            if ( $user ) {
+                my $sig = hmac_sha1_hex($message->{payload}, $user->{secret} );
+                if ( $sig ne $message->{sig} ) {
+                    $c->app->log->warn(
+                        "Invalid signature for " . $user->{username}
+                    );
+                    $user = undef;
+                }
             }
 
-            $c->schema->resultset('Socket')->update_or_create({
-                id        => $c->req->headers->header('Sec-WebSocket-Key'),
-                ip        => $ip,
-                keepalive => \'now()',
-                user_id   => $user ? $user->id : undef,
-            }, { key => $user ? 'user':'primary'} );
+            eval {
+                my $tx = $c->pg->db->begin;
+
+                $c->pg->db->delete('sockets', [
+                    {id      => $key},
+                    {user_id => $message->{payload}},
+                ]);
+
+                $c->pg->db->insert('sockets', {
+                    id        => $key,
+                    ip        => $ip,
+                    keepalive => \'now()',
+                    user_id   => $user ? $user->{id} : undef,
+                });
 
-            my $all = $c->schema->resultset('Socket_view')->count();
+                $tx->commit;
+            };
 
-            my $members = $c->schema->resultset('Socket_view')->count(
-                { is_member => 't' }
-            );
+            my $all = $c->pg->db->query(
+                'select count(*) from sockets_view'
+            )->hash->{count};
+
+            my $members = $c->pg->db->query(
+                'select count(*) from sockets_view where is_member'
+            )->hash->{count};
 
             my $group_size = $c->_member_group_size($members);
 
@@ -59,15 +82,14 @@ sub main {
             }}});
 
             if ( $user ) {
-                my $jitsi = $user->jitsi_allowed || $user->roles =~ /chairman/;
+                my $jitsi = $user->{jitsi_allowed} || $user->{roles} =~ /chairman|jitsi/;
 
                 $c->send({json => { event => 'user_status', payload => {
                     jitsi_allowed => $jitsi ? \1:\0,
-                    is_banned     => $user->banned_until ? \1:\0,
+                    is_banned     => $user->{banned_until} ? \1:\0,
                 }}});
             }
         }
-
     });
 
     $c->on(finish => sub ($c, $code, $reason = undef) {
-- 
GitLab