From fd8e04919c2ae1b879ce431c2149eddc56a6d7b0 Mon Sep 17 00:00:00 2001
From: xaralis <filip.varecha@fragaria.cz>
Date: Wed, 23 Dec 2020 20:19:20 +0100
Subject: [PATCH] feat: provide signature for keepalive

---
 package-lock.json    |  5 +++++
 package.json         |  1 +
 src/actions/users.js |  1 +
 src/ws/connection.js | 29 +++++++++++++++++++++++------
 typings/cf2021.d.ts  |  1 +
 5 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 825b7e4..519c083 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4316,6 +4316,11 @@
         "randomfill": "^1.0.3"
       }
     },
+    "crypto-js": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz",
+      "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg=="
+    },
     "css": {
       "version": "2.2.4",
       "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz",
diff --git a/package.json b/package.json
index 529a9a8..b1e1bec 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
     "@rooks/use-window-size": "^4.5.0",
     "@sentry/react": "^5.23.0",
     "classnames": "^2.2.6",
+    "crypto-js": "^4.0.0",
     "date-fns": "^2.16.1",
     "immer": "^7.0.15",
     "keycloak-js": "^10.0.2",
diff --git a/src/actions/users.js b/src/actions/users.js
index 49cf58b..3f5f5ef 100644
--- a/src/actions/users.js
+++ b/src/actions/users.js
@@ -27,6 +27,7 @@ export const loadMe = createAsyncAction(
             state.user.id = result.payload.id;
             state.user.group = result.payload.group;
             state.user.isBanned = result.payload.is_banned;
+            state.user.secret = result.payload.secret || "";
           }
         });
       }
diff --git a/src/ws/connection.js b/src/ws/connection.js
index 4882d1b..19ced7f 100644
--- a/src/ws/connection.js
+++ b/src/ws/connection.js
@@ -1,6 +1,8 @@
+import hex from "crypto-js/enc-hex";
+import hmacSHA1 from "crypto-js/hmac-sha1";
 import WaitQueue from "wait-queue";
 
-import { GlobalInfoStore } from "stores";
+import { AuthStore, GlobalInfoStore } from "stores";
 
 import { handlers } from "./handlers";
 
@@ -44,6 +46,18 @@ function Worker() {
   };
 }
 
+const buildKeepalivePayload = async () => {
+  const { user } = AuthStore.getRawState();
+  const payload = user && user.id ? user.id.toString() : "";
+  const signature = user.secret ? hmacSHA1(payload, user.secret) : null;
+
+  return {
+    event: "KEEPALIVE",
+    payload,
+    sig: hex.stringify(signature),
+  };
+};
+
 export const connect = ({ onConnect }) => {
   return new Promise((resolve, reject) => {
     const worker = Worker();
@@ -61,14 +75,17 @@ export const connect = ({ onConnect }) => {
         state.connectionState = "connected";
       });
       console.log("[ws] Connected.");
-      ws.send("CONNECT");
 
-      keepAliveInterval = setInterval(() => {
-        ws.send("KEEPALIVE");
+      const sendKeepalive = async () => {
+        ws.send(JSON.stringify(await buildKeepalivePayload()));
         console.debug("[ws] Sending keepalive.");
-      }, 30 * 1000);
+      };
+
+      sendKeepalive();
+
+      keepAliveInterval = setInterval(sendKeepalive, 15 * 1000);
 
-      const self = { ws, worker };
+      const self = { ws, worker, sendKeepalive };
 
       if (onConnect) {
         return onConnect(self).then(() => resolve(self));
diff --git a/typings/cf2021.d.ts b/typings/cf2021.d.ts
index fa510f2..4b9d628 100644
--- a/typings/cf2021.d.ts
+++ b/typings/cf2021.d.ts
@@ -46,6 +46,7 @@ declare namespace CF2021 {
       id?: number;
       isBanned?: boolean;
       group?: string;
+      secret?: string;
     };
   }
 
-- 
GitLab