From e9c5d17fcf2272ceadedbe313026914158259e13 Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Fri, 23 Sep 2022 17:41:34 +0100 Subject: [PATCH 1/3] feat(assist): socket validation middleware --- utilities/.gitignore | 4 +- utilities/package-lock.json | 198 ++++++++++++++++++++++++++++++++ utilities/package.json | 1 + utilities/run-dev.sh | 6 + utilities/servers/websocket.js | 4 +- utilities/utils/assistHelper.js | 57 ++++++++- 6 files changed, 265 insertions(+), 5 deletions(-) create mode 100755 utilities/run-dev.sh diff --git a/utilities/.gitignore b/utilities/.gitignore index 4486f0a7f..7a6a01b6e 100644 --- a/utilities/.gitignore +++ b/utilities/.gitignore @@ -3,4 +3,6 @@ node_modules npm-debug.log .cache test.html -.local \ No newline at end of file +.local + +*.mmdb \ No newline at end of file diff --git a/utilities/package-lock.json b/utilities/package-lock.json index f4eb45944..66bee4b50 100644 --- a/utilities/package-lock.json +++ b/utilities/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@maxmind/geoip2-node": "^3.4.0", "express": "^4.18.1", + "jsonwebtoken": "^8.5.1", "socket.io": "^4.5.1", "ua-parser-js": "^1.0.2" } @@ -102,6 +103,11 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -229,6 +235,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -487,6 +501,32 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", @@ -501,6 +541,60 @@ "verror": "1.10.0" } }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", @@ -726,6 +820,14 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -1060,6 +1162,11 @@ "unpipe": "1.0.0" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1150,6 +1257,14 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1351,6 +1466,30 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", @@ -1362,6 +1501,60 @@ "verror": "1.10.0" } }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", @@ -1505,6 +1698,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, "send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", diff --git a/utilities/package.json b/utilities/package.json index 41859ebc6..f798e73dd 100644 --- a/utilities/package.json +++ b/utilities/package.json @@ -20,6 +20,7 @@ "dependencies": { "@maxmind/geoip2-node": "^3.4.0", "express": "^4.18.1", + "jsonwebtoken": "^8.5.1", "socket.io": "^4.5.1", "ua-parser-js": "^1.0.2" } diff --git a/utilities/run-dev.sh b/utilities/run-dev.sh new file mode 100755 index 000000000..00e8d5a4b --- /dev/null +++ b/utilities/run-dev.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -a +source .env +set +a + +npm start \ No newline at end of file diff --git a/utilities/servers/websocket.js b/utilities/servers/websocket.js index d93ef671a..25bdf6a38 100644 --- a/utilities/servers/websocket.js +++ b/utilities/servers/websocket.js @@ -16,7 +16,8 @@ const { EVENTS_DEFINITION, extractSessionInfo, socketConnexionTimeout, - errorHandler + errorHandler, + authorizer } = require('../utils/assistHelper'); const wsRouter = express.Router(); @@ -241,6 +242,7 @@ module.exports = { wsRouter, start: (server, prefix) => { createSocketIOServer(server, prefix); + io.use(async (socket, next) => await authorizer.check(socket, next)); io.on('connection', async (socket) => { socket.on(EVENTS_DEFINITION.listen.ERROR, err => errorHandler(EVENTS_DEFINITION.listen.ERROR, err)); debug && console.log(`WS started:${socket.id}, Query:${JSON.stringify(socket.handshake.query)}`); diff --git a/utilities/utils/assistHelper.js b/utilities/utils/assistHelper.js index 212a3b93d..006223d25 100644 --- a/utilities/utils/assistHelper.js +++ b/utilities/utils/assistHelper.js @@ -1,7 +1,9 @@ +const jwt = require('jsonwebtoken'); const uaParser = require('ua-parser-js'); const {geoip} = require('./geoIP'); +const {extractPeerId} = require('./helper'); -let debug = process.env.debug === "1" || false; +let debug = process.env.debug === "1"; const IDENTITIES = {agent: 'agent', session: 'session'}; const EVENTS_DEFINITION = { listen: { @@ -92,7 +94,6 @@ function socketConnexionTimeout(io) { console.error(e); } }, 0.5 * 60 * 1000, io); - // }, 2.5 * 60 * 1000, io); } else { debug && console.log(`WS no manually disconnecting sockets.`); } @@ -103,6 +104,56 @@ function errorHandler(listenerName, error) { console.error(error); } + +function generateAccessToken(payload) { + return jwt.sign(payload, process.env.ASSIST_JWT_SECRET, {expiresIn: process.env.ASSIST_JWT_EXPIRATION || '30m'}); +} + + +const JWT_TOKEN_PREFIX = "Bearer "; + +function check(socket, next) { + if (socket.handshake.query.identity === IDENTITIES.session) { + return next(); + } + if (socket.handshake.query.peerId && socket.handshake.auth && socket.handshake.auth.token) { + let token = socket.handshake.auth.token; + if (token.startsWith(JWT_TOKEN_PREFIX)) { + token = token.substring(JWT_TOKEN_PREFIX.length); + } + jwt.verify(token, process.env.ASSIST_JWT_SECRET, (err, decoded) => { + debug && console.log("JWT payload:"); + debug && console.log(decoded); + if (err) { + debug && console.error(err); + return next(new Error('Authentication error')); + } + const {projectKey, sessionId} = extractPeerId(socket.handshake.query.peerId); + if (!projectKey || !sessionId) { + debug && console.error("Missing attribute:"); + debug && console.error(`projectKey:${projectKey}, sessionId:${sessionId}`); + return next(new Error('Authentication error')); + } + if (projectKey !== decoded.projectKey || sessionId !== decoded.sessionId) { + debug && console.error(`Trying to access projectKey:${projectKey} instead of ${decoded.projectKey}\nor`); + debug && console.error(`Trying to access sessionId:${sessionId} instead of ${decoded.sessionId}`); + return next(new Error('Authorization error')); + } + socket.decoded = decoded; + return next(); + }); + } else { + debug && console.error("something missing in:"); + debug && console.error(socket.handshake); + return next(new Error('Authentication error')); + } +} + module.exports = { - extractSessionInfo, EVENTS_DEFINITION, IDENTITIES, socketConnexionTimeout, errorHandler + extractSessionInfo, + EVENTS_DEFINITION, + IDENTITIES, + socketConnexionTimeout, + errorHandler, + authorizer: {generateAccessToken, check} }; \ No newline at end of file From 6b9b3ed552f16f16a2434f0bcd20bfa174da252e Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Fri, 23 Sep 2022 18:09:40 +0100 Subject: [PATCH 2/3] feat(assist): socket validation middleware --- ee/utilities/.gitignore | 2 + ee/utilities/package-lock.json | 186 ++++++++++++++++++++++ ee/utilities/package.json | 1 + ee/utilities/servers/websocket-cluster.js | 4 +- ee/utilities/servers/websocket.js | 4 +- 5 files changed, 195 insertions(+), 2 deletions(-) diff --git a/ee/utilities/.gitignore b/ee/utilities/.gitignore index a11e6be97..8c9dca279 100644 --- a/ee/utilities/.gitignore +++ b/ee/utilities/.gitignore @@ -15,3 +15,5 @@ servers/sourcemaps-server.js /utils/helper.js /utils/assistHelper.js .local +run-dev.sh +*.mmdb diff --git a/ee/utilities/package-lock.json b/ee/utilities/package-lock.json index 1c14c5f25..ace7a2109 100644 --- a/ee/utilities/package-lock.json +++ b/ee/utilities/package-lock.json @@ -12,6 +12,7 @@ "@maxmind/geoip2-node": "^3.4.0", "@socket.io/redis-adapter": "^7.2.0", "express": "^4.18.1", + "jsonwebtoken": "^8.5.1", "redis": "^4.2.0", "socket.io": "^4.5.1", "ua-parser-js": "^1.0.2", @@ -185,6 +186,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -328,6 +334,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -599,6 +613,27 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, "node_modules/jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", @@ -613,6 +648,60 @@ "verror": "1.10.0" } }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", @@ -856,6 +945,14 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -1241,6 +1338,11 @@ } } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1336,6 +1438,14 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1559,6 +1669,23 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + } + }, "jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", @@ -1570,6 +1697,60 @@ "verror": "1.10.0" } }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", @@ -1731,6 +1912,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, "send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", diff --git a/ee/utilities/package.json b/ee/utilities/package.json index ba3997a90..5dfd325af 100644 --- a/ee/utilities/package.json +++ b/ee/utilities/package.json @@ -21,6 +21,7 @@ "@maxmind/geoip2-node": "^3.4.0", "@socket.io/redis-adapter": "^7.2.0", "express": "^4.18.1", + "jsonwebtoken": "^8.5.1", "redis": "^4.2.0", "socket.io": "^4.5.1", "ua-parser-js": "^1.0.2", diff --git a/ee/utilities/servers/websocket-cluster.js b/ee/utilities/servers/websocket-cluster.js index ab3d3ea59..6aa2bade5 100644 --- a/ee/utilities/servers/websocket-cluster.js +++ b/ee/utilities/servers/websocket-cluster.js @@ -13,7 +13,8 @@ const { EVENTS_DEFINITION, extractSessionInfo, socketConnexionTimeout, - errorHandler + errorHandler, + authorizer } = require('../utils/assistHelper'); const { extractProjectKeyFromRequest, @@ -282,6 +283,7 @@ module.exports = { wsRouter, start: (server, prefix) => { createSocketIOServer(server, prefix); + io.use(async (socket, next) => await authorizer.check(socket, next)); io.on('connection', async (socket) => { socket.on(EVENTS_DEFINITION.listen.ERROR, err => errorHandler(EVENTS_DEFINITION.listen.ERROR, err)); debug && console.log(`WS started:${socket.id}, Query:${JSON.stringify(socket.handshake.query)}`); diff --git a/ee/utilities/servers/websocket.js b/ee/utilities/servers/websocket.js index 259838fb1..bf65789f2 100644 --- a/ee/utilities/servers/websocket.js +++ b/ee/utilities/servers/websocket.js @@ -13,7 +13,8 @@ const { EVENTS_DEFINITION, extractSessionInfo, socketConnexionTimeout, - errorHandler + errorHandler, + authorizer } = require('../utils/assistHelper'); const { extractProjectKeyFromRequest, @@ -260,6 +261,7 @@ module.exports = { wsRouter, start: (server, prefix) => { createSocketIOServer(server, prefix); + io.use(async (socket, next) => await authorizer.check(socket, next)); io.on('connection', async (socket) => { socket.on(EVENTS_DEFINITION.listen.ERROR, err => errorHandler(EVENTS_DEFINITION.listen.ERROR, err)); debug && console.log(`WS started:${socket.id}, Query:${JSON.stringify(socket.handshake.query)}`); From 18d4f17775e80be972b685db680afafedd55f9d9 Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Mon, 26 Sep 2022 16:33:35 +0200 Subject: [PATCH 3/3] feat(chalice): upgraded dependencies feat(chalice): refactored code feat(chalice): assist validate session by DB feat(chalice): assist validate session by Live sessions feat(chalice): assist generate agent's token --- api/Dockerfile.alerts | 4 +- api/chalicelib/core/assist.py | 111 ++++++++++++++++++-------- api/chalicelib/core/authorizers.py | 4 +- api/chalicelib/core/users.py | 11 +-- api/chalicelib/utils/helper.py | 16 +--- api/chalicelib/utils/pg_client.py | 10 +-- api/env.default | 23 +++--- api/requirements-alerts.txt | 16 ++-- api/requirements.txt | 16 ++-- api/routers/core.py | 25 +----- api/routers/core_dynamic.py | 32 +++++--- ee/api/Dockerfile.alerts | 4 +- ee/api/Dockerfile.crons | 4 +- ee/api/chalicelib/core/authorizers.py | 4 +- ee/api/chalicelib/core/users.py | 11 +-- ee/api/env.default | 18 ++--- ee/api/requirements-alerts.txt | 16 ++-- ee/api/requirements-crons.txt | 16 ++-- ee/api/requirements.txt | 16 ++-- ee/api/routers/core_dynamic.py | 32 +++++--- 20 files changed, 193 insertions(+), 196 deletions(-) diff --git a/api/Dockerfile.alerts b/api/Dockerfile.alerts index ab3732c91..f367dc5a2 100644 --- a/api/Dockerfile.alerts +++ b/api/Dockerfile.alerts @@ -4,8 +4,8 @@ LABEL Maintainer="KRAIEM Taha Yassine" RUN apk add --no-cache build-base tini ARG envarg ENV APP_NAME=alerts \ - pg_minconn=1 \ - pg_maxconn=10 \ + PG_MINCONN=1 \ + PG_MAXCONN=10 \ LISTEN_PORT=8000 \ ENTERPRISE_BUILD=${envarg} diff --git a/api/chalicelib/core/assist.py b/api/chalicelib/core/assist.py index 8b908b004..3cd3cec25 100644 --- a/api/chalicelib/core/assist.py +++ b/api/chalicelib/core/assist.py @@ -1,12 +1,14 @@ from os import access, R_OK -from os.path import exists +from os.path import exists as path_exists +import jwt import requests from decouple import config from starlette.exceptions import HTTPException import schemas from chalicelib.core import projects +from chalicelib.utils.TimeUTC import TimeUTC ASSIST_KEY = config("ASSIST_KEY") ASSIST_URL = config("ASSIST_URL") % ASSIST_KEY @@ -51,13 +53,13 @@ def get_live_sessions_ws(project_id, body: schemas.LiveSessionsSearchPayloadSche def __get_live_sessions_ws(project_id, data): project_key = projects.get_project_key(project_id) try: - connected_peers = requests.post(ASSIST_URL + config("assist") + f"/{project_key}", - json=data, timeout=config("assistTimeout", cast=int, default=5)) - if connected_peers.status_code != 200: - print("!! issue with the peer-server") - print(connected_peers.text) + results = requests.post(ASSIST_URL + config("assist") + f"/{project_key}", + json=data, timeout=config("assistTimeout", cast=int, default=5)) + if results.status_code != 200: + print(f"!! issue with the peer-server code:{results.status_code}") + print(results.text) return {"total": 0, "sessions": []} - live_peers = connected_peers.json().get("data", []) + live_peers = results.json().get("data", []) except requests.exceptions.Timeout: print("Timeout getting Assist response") live_peers = {"total": 0, "sessions": []} @@ -66,7 +68,7 @@ def __get_live_sessions_ws(project_id, data): print(str(e)) print("expected JSON, received:") try: - print(connected_peers.text) + print(results.text) except: print("couldn't get response") live_peers = {"total": 0, "sessions": []} @@ -79,45 +81,63 @@ def __get_live_sessions_ws(project_id, data): return live_peers +def __get_agent_token(project_id, project_key, session_id): + iat = TimeUTC.now() + return jwt.encode( + payload={ + "projectKey": project_key, + "projectId": project_id, + "sessionId": session_id, + "iat": iat // 1000, + "exp": iat // 1000 + config("JWT_EXP_DELTA_SECONDS", cast=int) + TimeUTC.get_utc_offset() // 1000, + "iss": config("JWT_ISSUER"), + "aud": f"openreplay:agent" + }, + key=config("jwt_secret"), + algorithm=config("jwt_algorithm") + ) + + def get_live_session_by_id(project_id, session_id): project_key = projects.get_project_key(project_id) try: - connected_peers = requests.get(ASSIST_URL + config("assist") + f"/{project_key}/{session_id}", - timeout=config("assistTimeout", cast=int, default=5)) - if connected_peers.status_code != 200: - print("!! issue with the peer-server") - print(connected_peers.text) - return False - connected_peers = connected_peers.json().get("data") - if connected_peers is None: + results = requests.get(ASSIST_URL + config("assist") + f"/{project_key}/{session_id}", + timeout=config("assistTimeout", cast=int, default=5)) + if results.status_code != 200: + print(f"!! issue with the peer-server code:{results.status_code}") + print(results.text) return None - connected_peers["live"] = True + results = results.json().get("data") + if results is None: + return None + results["live"] = True + results["agentToken"] = __get_agent_token(project_id=project_id, project_key=project_key, session_id=session_id) except requests.exceptions.Timeout: - print("Timeout getting Assist response") + print("!! Timeout getting Assist response") return None except Exception as e: print("issue getting Assist response") print(str(e)) print("expected JSON, received:") try: - print(connected_peers.text) + print(results.text) except: print("couldn't get response") return None - return connected_peers + return results def is_live(project_id, session_id, project_key=None): if project_key is None: project_key = projects.get_project_key(project_id) try: - connected_peers = requests.get(ASSIST_URL + config("assistList") + f"/{project_key}/{session_id}", - timeout=config("assistTimeout", cast=int, default=5)) - if connected_peers.status_code != 200: - print("!! issue with the peer-server") - print(connected_peers.text) + results = requests.get(ASSIST_URL + config("assistList") + f"/{project_key}/{session_id}", + timeout=config("assistTimeout", cast=int, default=5)) + if results.status_code != 200: + print(f"!! issue with the peer-server code:{results.status_code}") + print(results.text) return False - connected_peers = connected_peers.json().get("data") + results = results.json().get("data") except requests.exceptions.Timeout: print("Timeout getting Assist response") return False @@ -126,11 +146,11 @@ def is_live(project_id, session_id, project_key=None): print(str(e)) print("expected JSON, received:") try: - print(connected_peers.text) + print(results.text) except: print("couldn't get response") return False - return str(session_id) == connected_peers + return str(session_id) == results def autocomplete(project_id, q: str, key: str = None): @@ -143,7 +163,7 @@ def autocomplete(project_id, q: str, key: str = None): ASSIST_URL + config("assistList") + f"/{project_key}/autocomplete", params=params, timeout=config("assistTimeout", cast=int, default=5)) if results.status_code != 200: - print("!! issue with the peer-server") + print(f"!! issue with the peer-server code:{results.status_code}") print(results.text) return {"errors": [f"Something went wrong wile calling assist:{results.text}"]} results = results.json().get("data", []) @@ -169,7 +189,7 @@ def get_ice_servers(): def __get_efs_path(): efs_path = config("FS_DIR") - if not exists(efs_path): + if not path_exists(efs_path): raise HTTPException(400, f"EFS not found in path: {efs_path}") if not access(efs_path, R_OK): @@ -185,7 +205,7 @@ def __get_mob_path(project_id, session_id): def get_raw_mob_by_id(project_id, session_id): efs_path = __get_efs_path() path_to_file = efs_path + "/" + __get_mob_path(project_id=project_id, session_id=session_id) - if exists(path_to_file): + if path_exists(path_to_file): if not access(path_to_file, R_OK): raise HTTPException(400, f"Replay file found under: {efs_path};" f" but it is not readable, please check permissions") @@ -203,7 +223,7 @@ def __get_devtools_path(project_id, session_id): def get_raw_devtools_by_id(project_id, session_id): efs_path = __get_efs_path() path_to_file = efs_path + "/" + __get_devtools_path(project_id=project_id, session_id=session_id) - if exists(path_to_file): + if path_exists(path_to_file): if not access(path_to_file, R_OK): raise HTTPException(400, f"Devtools file found under: {efs_path};" f" but it is not readable, please check permissions") @@ -211,3 +231,30 @@ def get_raw_devtools_by_id(project_id, session_id): return path_to_file return None + + +def session_exists(project_id, session_id): + project_key = projects.get_project_key(project_id) + try: + results = requests.get(ASSIST_URL + config("assist") + f"/{project_key}/{session_id}", + timeout=config("assistTimeout", cast=int, default=5)) + if results.status_code != 200: + print(f"!! issue with the peer-server code:{results.status_code}") + print(results.text) + return None + results = results.json().get("data") + if results is None: + return False + return True + except requests.exceptions.Timeout: + print("!! Timeout getting Assist response") + return False + except Exception as e: + print("issue getting Assist response") + print(str(e)) + print("expected JSON, received:") + try: + print(results.text) + except: + print("couldn't get response") + return False diff --git a/api/chalicelib/core/authorizers.py b/api/chalicelib/core/authorizers.py index 5756e82ab..c32f08208 100644 --- a/api/chalicelib/core/authorizers.py +++ b/api/chalicelib/core/authorizers.py @@ -42,8 +42,8 @@ def generate_jwt(id, tenant_id, iat, aud): payload={ "userId": id, "tenantId": tenant_id, - "exp": iat // 1000 + config("jwt_exp_delta_seconds", cast=int) + TimeUTC.get_utc_offset() // 1000, - "iss": config("jwt_issuer"), + "exp": iat // 1000 + config("ASSIST_JWT_EXPIRATION", cast=int) + TimeUTC.get_utc_offset() // 1000, + "iss": config("JWT_ISSUER"), "iat": iat // 1000, "aud": aud }, diff --git a/api/chalicelib/core/users.py b/api/chalicelib/core/users.py index 0ea8ed594..9af070fc5 100644 --- a/api/chalicelib/core/users.py +++ b/api/chalicelib/core/users.py @@ -195,13 +195,6 @@ def create_member(tenant_id, user_id, data, background_tasks: BackgroundTasks): admin=data.get("admin", False), name=name) new_member["invitationLink"] = __get_invitation_link(new_member.pop("invitationToken")) - # helper.async_post(config('email_basic') % 'member_invitation', - # { - # "email": data["email"], - # "invitationLink": new_member["invitationLink"], - # "clientId": tenants.get_by_tenant_id(tenant_id)["name"], - # "senderName": admin["name"] - # }) background_tasks.add_task(email_helper.send_team_invitation, **{ "recipient": data["email"], "invitation_link": new_member["invitationLink"], @@ -552,7 +545,7 @@ def auth_exists(user_id, tenant_id, jwt_iat, jwt_aud): ) -def authenticate(email, password, for_change_password=False, for_plugin=False): +def authenticate(email, password, for_change_password=False): with pg_client.PostgresClient() as cur: query = cur.mogrify( f"""SELECT @@ -587,7 +580,7 @@ def authenticate(email, password, for_change_password=False, for_plugin=False): return { "jwt": authorizers.generate_jwt(r['userId'], r['tenantId'], TimeUTC.datetime_to_timestamp(cur.fetchone()["jwt_iat"]), - aud=f"plugin:{helper.get_stage_name()}" if for_plugin else f"front:{helper.get_stage_name()}"), + aud=f"front:{helper.get_stage_name()}"), "email": email, **r } diff --git a/api/chalicelib/utils/helper.py b/api/chalicelib/utils/helper.py index b04b8aa43..192c309f5 100644 --- a/api/chalicelib/utils/helper.py +++ b/api/chalicelib/utils/helper.py @@ -18,7 +18,7 @@ def get_version_number(): def get_stage_name(): - stage = config("stage") + stage = config("STAGE") return stage[len(local_prefix):] if stage.startswith(local_prefix) else stage @@ -35,7 +35,7 @@ def is_onprem(): def is_local(): - return config("stage").startswith(local_prefix) + return config("STAGE").startswith(local_prefix) def generate_salt(): @@ -141,18 +141,6 @@ def allow_captcha(): and len(config("captcha_server")) > 0 and len(config("captcha_key")) > 0 -def allow_sentry(): - return config("sentryURL", default=None) is not None and len(config("sentryURL")) > 0 - - -def async_post(endpoint, data): - data["auth"] = config("async_Token") - try: - requests.post(endpoint, timeout=1, json=data) - except requests.exceptions.ReadTimeout: - pass - - def string_to_sql_like(value): value = re.sub(' +', ' ', value) value = value.replace("*", "%") diff --git a/api/chalicelib/utils/pg_client.py b/api/chalicelib/utils/pg_client.py index 8b9001649..fe71f997b 100644 --- a/api/chalicelib/utils/pg_client.py +++ b/api/chalicelib/utils/pg_client.py @@ -17,8 +17,8 @@ _PG_CONFIG = {"host": config("pg_host"), "port": config("pg_port", cast=int), "application_name": config("APP_NAME", default="PY")} PG_CONFIG = dict(_PG_CONFIG) -if config("pg_timeout", cast=int, default=0) > 0: - PG_CONFIG["options"] = f"-c statement_timeout={config('pg_timeout', cast=int) * 1000}" +if config("PG_TIMEOUT", cast=int, default=0) > 0: + PG_CONFIG["options"] = f"-c statement_timeout={config('PG_TIMEOUT', cast=int) * 1000}" logging.info(f">PG_POOL:{config('PG_POOL', default=None)}") @@ -67,8 +67,8 @@ def make_pool(): except (Exception, psycopg2.DatabaseError) as error: logging.error("Error while closing all connexions to PostgreSQL", error) try: - postgreSQL_pool = ORThreadedConnectionPool(config("pg_minconn", cast=int, default=20), - config("pg_maxconn", cast=int, default=80), + postgreSQL_pool = ORThreadedConnectionPool(config("PG_MINCONN", cast=int, default=20), + config("PG_MAXCONN", cast=int, default=80), **PG_CONFIG) if (postgreSQL_pool): logging.info("Connection pool created successfully") @@ -109,7 +109,7 @@ class PostgresClient: elif not config('PG_POOL', cast=bool, default=True): single_config = dict(_PG_CONFIG) single_config["application_name"] += "-NOPOOL" - single_config["options"] = f"-c statement_timeout={config('pg_timeout', cast=int, default=3 * 60) * 1000}" + single_config["options"] = f"-c statement_timeout={config('PG_TIMEOUT', cast=int, default=3 * 60) * 1000}" self.connection = psycopg2.connect(**single_config) else: self.connection = postgreSQL_pool.getconn() diff --git a/api/env.default b/api/env.default index d09e9b57c..703cdc887 100644 --- a/api/env.default +++ b/api/env.default @@ -12,19 +12,14 @@ S3_KEY= S3_SECRET= SITE_URL= announcement_url= -async_Token= captcha_key= captcha_server= change_password_link=/reset-password?invitation=%s&&pass=%s -email_basic=http://127.0.0.1:8000/async/basic/%s -email_signup=http://127.0.0.1:8000/async/email_signup/%s invitation_link=/api/users/invitation?token=%s -isEE=false -isFOS=true js_cache_bucket=sessions-assets jwt_algorithm=HS512 -jwt_exp_delta_seconds=2592000 -jwt_issuer=openreplay-default-foss +JWT_EXP_DELTA_SECONDS=2592000 +JWT_ISSUER=openreplay-oss jwt_secret="SET A RANDOM STRING HERE" ASSIST_URL=http://assist-openreplay.app.svc.cluster.local:9001/assist/%s assist=/sockets-live @@ -34,19 +29,17 @@ pg_host=postgresql.db.svc.cluster.local pg_password=asayerPostgres pg_port=5432 pg_user=postgres -pg_timeout=30 -pg_minconn=20 -pg_maxconn=50 +PG_TIMEOUT=30 +PG_MINCONN=20 +PG_MAXCONN=50 PG_RETRY_MAX=50 PG_RETRY_INTERVAL=2 PG_POOL=true -put_S3_TTL=20 -sentryURL= sessions_bucket=mobs sessions_region=us-east-1 sourcemaps_bucket=sourcemaps sourcemaps_reader=http://127.0.0.1:9000/sourcemaps/%s/sourcemaps -stage=default-foss +STAGE=default-foss version_number=1.4.0 FS_DIR=/mnt/efs EFS_SESSION_MOB_PATTERN=%(sessionId)s/dom.mob @@ -54,4 +47,6 @@ EFS_DEVTOOLS_MOB_PATTERN=%(sessionId)s/devtools.mob SESSION_MOB_PATTERN_S=%(sessionId)s/dom.mobs SESSION_MOB_PATTERN_E=%(sessionId)s/dom.mobe DEVTOOLS_MOB_PATTERN=%(sessionId)s/devtools.mob -PRESIGNED_URL_EXPIRATION=3600 \ No newline at end of file +PRESIGNED_URL_EXPIRATION=3600 +ASSIST_JWT_EXPIRATION=1800 +ASSIST_JWT_SECRET= \ No newline at end of file diff --git a/api/requirements-alerts.txt b/api/requirements-alerts.txt index fc141eb09..11f961615 100644 --- a/api/requirements-alerts.txt +++ b/api/requirements-alerts.txt @@ -1,15 +1,15 @@ requests==2.28.1 -urllib3==1.26.10 -boto3==1.24.53 -pyjwt==2.4.0 +urllib3==1.26.12 +boto3==1.24.80 +pyjwt==2.5.0 psycopg2-binary==2.9.3 -elasticsearch==8.3.3 -jira==3.3.1 +elasticsearch==8.4.2 +jira==3.4.1 -fastapi==0.80.0 -uvicorn[standard]==0.18.2 +fastapi==0.85.0 +uvicorn[standard]==0.18.3 python-decouple==3.6 -pydantic[email]==1.9.2 +pydantic[email]==1.10.2 apscheduler==3.9.1 \ No newline at end of file diff --git a/api/requirements.txt b/api/requirements.txt index fc141eb09..11f961615 100644 --- a/api/requirements.txt +++ b/api/requirements.txt @@ -1,15 +1,15 @@ requests==2.28.1 -urllib3==1.26.10 -boto3==1.24.53 -pyjwt==2.4.0 +urllib3==1.26.12 +boto3==1.24.80 +pyjwt==2.5.0 psycopg2-binary==2.9.3 -elasticsearch==8.3.3 -jira==3.3.1 +elasticsearch==8.4.2 +jira==3.4.1 -fastapi==0.80.0 -uvicorn[standard]==0.18.2 +fastapi==0.85.0 +uvicorn[standard]==0.18.3 python-decouple==3.6 -pydantic[email]==1.9.2 +pydantic[email]==1.10.2 apscheduler==3.9.1 \ No newline at end of file diff --git a/api/routers/core.py b/api/routers/core.py index 3741fdec6..18e459dd2 100644 --- a/api/routers/core.py +++ b/api/routers/core.py @@ -31,7 +31,7 @@ def login(data: schemas.UserLoginSchema = Body(...)): detail="Invalid captcha." ) - r = users.authenticate(data.email, data.password, for_plugin=False) + r = users.authenticate(data.email, data.password) if r is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -546,21 +546,6 @@ def search_integrations(projectId: int, context: schemas.CurrentContext = Depend return log_tools.search(project_id=projectId) -@public_app.post('/async/email_assignment', tags=["async mail"]) -def async_send_signup_emails(data: schemas.EmailPayloadSchema = Body(...)): - if data.auth != config("async_Token"): - return {} - email_helper.send_assign_session(recipient=data.email, link=data.link, message=data.message) - - -# @public_app.post('/async/basic/member_invitation', tags=["async mail"]) -# def async_basic_emails(data: schemas.MemberInvitationPayloadSchema = Body(...)): -# if data.auth != config("async_Token"): -# return {} -# email_helper.send_team_invitation(recipient=data.email, invitation_link=data.invitation_link, -# client_id=data.client_id, sender_name=data.sender_name) - - @app.get('/{projectId}/sample_rate', tags=["projects"]) def get_capture_status(projectId: int, context: schemas.CurrentContext = Depends(OR_context)): return {"data": projects.get_capture_status(project_id=projectId)} @@ -877,14 +862,6 @@ def batch_view_notifications(data: schemas.NotificationsViewSchema, tenant_id=context.tenant_id)} -@public_app.post('/notifications', tags=['notifications']) -@public_app.put('/notifications', tags=['notifications']) -def create_notifications(data: schemas.CreateNotificationSchema): - if data.token != config("async_Token"): - return {"errors": ["missing token"]} - return notifications.create(data.notifications) - - @app.get('/boarding', tags=['boarding']) def get_boarding_state(context: schemas.CurrentContext = Depends(OR_context)): return {"data": boarding.get_state(tenant_id=context.tenant_id)} diff --git a/api/routers/core_dynamic.py b/api/routers/core_dynamic.py index a4e051249..a9b50b4dc 100644 --- a/api/routers/core_dynamic.py +++ b/api/routers/core_dynamic.py @@ -279,16 +279,19 @@ def get_live_session(projectId: int, sessionId: str, background_tasks: Backgroun @app.get('/{projectId}/assist/sessions/{sessionId}/replay', tags=["assist"]) def get_live_session_replay_file(projectId: int, sessionId: Union[int, str], context: schemas.CurrentContext = Depends(OR_context)): - if isinstance(sessionId, str) or not sessions.session_exists(project_id=projectId, session_id=sessionId): - if isinstance(sessionId, str): - print(f"{sessionId} not a valid number.") - else: - print(f"{projectId}/{sessionId} not found in DB.") + not_found = {"errors": ["Replay file not found"]} + if isinstance(sessionId, str): + print(f"{sessionId} not a valid number.") + return not_found + if not sessions.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in DB.") + if not assist.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in Assist.") + return not_found - return {"errors": ["Replay file not found"]} path = assist.get_raw_mob_by_id(project_id=projectId, session_id=sessionId) if path is None: - return {"errors": ["Replay file not found"]} + return not_found return FileResponse(path=path, media_type="application/octet-stream") @@ -297,13 +300,16 @@ def get_live_session_replay_file(projectId: int, sessionId: Union[int, str], @app.get('/{projectId}/assist/sessions/{sessionId}/devtools', tags=["assist"]) def get_live_session_devtools_file(projectId: int, sessionId: Union[int, str], context: schemas.CurrentContext = Depends(OR_context)): - if isinstance(sessionId, str) or not sessions.session_exists(project_id=projectId, session_id=sessionId): - if isinstance(sessionId, str): - print(f"{sessionId} not a valid number.") - else: - print(f"{projectId}/{sessionId} not found in DB.") + not_found = {"errors": ["Devtools file not found"]} + if isinstance(sessionId, str): + print(f"{sessionId} not a valid number.") + return not_found + if not sessions.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in DB.") + if not assist.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in Assist.") + return not_found - return {"errors": ["Devtools file not found"]} path = assist.get_raw_devtools_by_id(project_id=projectId, session_id=sessionId) if path is None: return {"errors": ["Devtools file not found"]} diff --git a/ee/api/Dockerfile.alerts b/ee/api/Dockerfile.alerts index 02bac9350..303502cb2 100644 --- a/ee/api/Dockerfile.alerts +++ b/ee/api/Dockerfile.alerts @@ -4,8 +4,8 @@ LABEL Maintainer="KRAIEM Taha Yassine" RUN apk add --no-cache build-base tini ARG envarg ENV APP_NAME=alerts \ - pg_minconn=1 \ - pg_maxconn=10 \ + PG_MINCONN=1 \ + PG_MAXCONN=10 \ LISTEN_PORT=8000 \ ENTERPRISE_BUILD=${envarg} diff --git a/ee/api/Dockerfile.crons b/ee/api/Dockerfile.crons index 83b3085e0..4108b361e 100644 --- a/ee/api/Dockerfile.crons +++ b/ee/api/Dockerfile.crons @@ -4,8 +4,8 @@ LABEL Maintainer="KRAIEM Taha Yassine" RUN apk add --no-cache build-base tini ARG envarg ENV APP_NAME=crons \ - pg_minconn=2 \ - pg_maxconn=10 \ + PG_MINCONN=2 \ + PG_MAXCONN=10 \ ENTERPRISE_BUILD=${envarg} \ ACTION="" \ PG_POOL=false diff --git a/ee/api/chalicelib/core/authorizers.py b/ee/api/chalicelib/core/authorizers.py index 5adf3e61a..b080d94ef 100644 --- a/ee/api/chalicelib/core/authorizers.py +++ b/ee/api/chalicelib/core/authorizers.py @@ -43,9 +43,9 @@ def generate_jwt(id, tenant_id, iat, aud, exp=None): payload={ "userId": id, "tenantId": tenant_id, - "exp": iat // 1000 + int(config("jwt_exp_delta_seconds")) + TimeUTC.get_utc_offset() // 1000 \ + "exp": iat // 1000 + int(config("JWT_EXP_DELTA_SECONDS")) + TimeUTC.get_utc_offset() // 1000 \ if exp is None else exp+ TimeUTC.get_utc_offset() // 1000, - "iss": config("jwt_issuer"), + "iss": config("JWT_ISSUER"), "iat": iat // 1000, "aud": aud }, diff --git a/ee/api/chalicelib/core/users.py b/ee/api/chalicelib/core/users.py index ae998f83f..661194bbb 100644 --- a/ee/api/chalicelib/core/users.py +++ b/ee/api/chalicelib/core/users.py @@ -228,13 +228,6 @@ def create_member(tenant_id, user_id, data, background_tasks: BackgroundTasks): new_member = create_new_member(tenant_id=tenant_id, email=data["email"], invitation_token=invitation_token, admin=data.get("admin", False), name=name, role_id=role_id) new_member["invitationLink"] = __get_invitation_link(new_member.pop("invitationToken")) - # helper.async_post(config('email_basic') % 'member_invitation', - # { - # "email": data["email"], - # "invitationLink": new_member["invitationLink"], - # "clientId": tenants.get_by_tenant_id(tenant_id)["name"], - # "senderName": admin["name"] - # }) background_tasks.add_task(email_helper.send_team_invitation, **{ "recipient": data["email"], "invitation_link": new_member["invitationLink"], @@ -628,7 +621,7 @@ def change_jwt_iat(user_id): return cur.fetchone().get("jwt_iat") -def authenticate(email, password, for_change_password=False, for_plugin=False): +def authenticate(email, password, for_change_password=False): with pg_client.PostgresClient() as cur: query = cur.mogrify( f"""SELECT @@ -675,7 +668,7 @@ def authenticate(email, password, for_change_password=False, for_plugin=False): return { "jwt": authorizers.generate_jwt(r['userId'], r['tenantId'], TimeUTC.datetime_to_timestamp(jwt_iat), - aud=f"plugin:{helper.get_stage_name()}" if for_plugin else f"front:{helper.get_stage_name()}"), + aud=f"front:{helper.get_stage_name()}"), "email": email, **r } diff --git a/ee/api/env.default b/ee/api/env.default index 3fc6add36..8f0765d92 100644 --- a/ee/api/env.default +++ b/ee/api/env.default @@ -14,7 +14,6 @@ S3_SECRET= SAML2_MD_URL= SITE_URL= announcement_url= -async_Token= captcha_key= captcha_server= ch_host= @@ -22,20 +21,15 @@ ch_port= ch_timeout=30 ch_receive_timeout=10 change_password_link=/reset-password?invitation=%s&&pass=%s -email_basic=http://127.0.0.1:8000/async/basic/%s -email_plans=http://127.0.0.1:8000/async/plans/%s -email_signup=http://127.0.0.1:8000/async/email_signup/%s idp_entityId= idp_sls_url= idp_sso_url= idp_x509cert= invitation_link=/api/users/invitation?token=%s -isEE=true -isFOS=false js_cache_bucket=sessions-assets jwt_algorithm=HS512 -jwt_exp_delta_seconds=2592000 -jwt_issuer=openreplay-default-ee +JWT_EXP_DELTA_SECONDS=2592000 +JWT_ISSUER=openreplay-ee jwt_secret="SET A RANDOM STRING HERE" ASSIST_URL=http://assist-openreplay.app.svc.cluster.local:9001/assist/%s assist=/sockets-live @@ -45,14 +39,12 @@ pg_host=postgresql.db.svc.cluster.local pg_password=asayerPostgres pg_port=5432 pg_user=postgres -pg_timeout=30 -pg_minconn=20 -pg_maxconn=50 +PG_TIMEOUT=30 +PG_MINCONN=20 +PG_MAXCONN=50 PG_RETRY_MAX=50 PG_RETRY_INTERVAL=2 PG_POOL=true -put_S3_TTL=20 -sentryURL= sessions_bucket=mobs sessions_region=us-east-1 sourcemaps_bucket=sourcemaps diff --git a/ee/api/requirements-alerts.txt b/ee/api/requirements-alerts.txt index 475a39b5e..19c4390fd 100644 --- a/ee/api/requirements-alerts.txt +++ b/ee/api/requirements-alerts.txt @@ -1,17 +1,17 @@ requests==2.28.1 -urllib3==1.26.10 -boto3==1.24.53 -pyjwt==2.4.0 +urllib3==1.26.12 +boto3==1.24.80 +pyjwt==2.5.0 psycopg2-binary==2.9.3 -elasticsearch==8.3.3 -jira==3.3.1 +elasticsearch==8.4.2 +jira==3.4.1 -fastapi==0.80.0 -uvicorn[standard]==0.18.2 +fastapi==0.85.0 +uvicorn[standard]==0.18.3 python-decouple==3.6 -pydantic[email]==1.9.2 +pydantic[email]==1.10.2 apscheduler==3.9.1 clickhouse-driver==0.2.4 diff --git a/ee/api/requirements-crons.txt b/ee/api/requirements-crons.txt index 475a39b5e..19c4390fd 100644 --- a/ee/api/requirements-crons.txt +++ b/ee/api/requirements-crons.txt @@ -1,17 +1,17 @@ requests==2.28.1 -urllib3==1.26.10 -boto3==1.24.53 -pyjwt==2.4.0 +urllib3==1.26.12 +boto3==1.24.80 +pyjwt==2.5.0 psycopg2-binary==2.9.3 -elasticsearch==8.3.3 -jira==3.3.1 +elasticsearch==8.4.2 +jira==3.4.1 -fastapi==0.80.0 -uvicorn[standard]==0.18.2 +fastapi==0.85.0 +uvicorn[standard]==0.18.3 python-decouple==3.6 -pydantic[email]==1.9.2 +pydantic[email]==1.10.2 apscheduler==3.9.1 clickhouse-driver==0.2.4 diff --git a/ee/api/requirements.txt b/ee/api/requirements.txt index bdf363b7b..c4023ce5c 100644 --- a/ee/api/requirements.txt +++ b/ee/api/requirements.txt @@ -1,17 +1,17 @@ requests==2.28.1 -urllib3==1.26.10 -boto3==1.24.53 -pyjwt==2.4.0 +urllib3==1.26.12 +boto3==1.24.80 +pyjwt==2.5.0 psycopg2-binary==2.9.3 -elasticsearch==8.3.3 -jira==3.3.1 +elasticsearch==8.4.2 +jira==3.4.1 -fastapi==0.80.0 -uvicorn[standard]==0.18.2 +fastapi==0.85.0 +uvicorn[standard]==0.18.3 python-decouple==3.6 -pydantic[email]==1.9.2 +pydantic[email]==1.10.2 apscheduler==3.9.1 clickhouse-driver==0.2.4 diff --git a/ee/api/routers/core_dynamic.py b/ee/api/routers/core_dynamic.py index fa5528e6e..ed31fd56c 100644 --- a/ee/api/routers/core_dynamic.py +++ b/ee/api/routers/core_dynamic.py @@ -291,16 +291,19 @@ def get_live_session(projectId: int, sessionId: str, background_tasks: Backgroun dependencies=[OR_scope(Permissions.assist_live, Permissions.session_replay)]) def get_live_session_replay_file(projectId: int, sessionId: Union[int, str], context: schemas.CurrentContext = Depends(OR_context)): - if isinstance(sessionId, str) or not sessions.session_exists(project_id=projectId, session_id=sessionId): - if isinstance(sessionId, str): - print(f"{sessionId} not a valid number.") - else: - print(f"{projectId}/{sessionId} not found in DB.") + not_found = {"errors": ["Replay file not found"]} + if isinstance(sessionId, str): + print(f"{sessionId} not a valid number.") + return not_found + if not sessions.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in DB.") + if not assist.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in Assist.") + return not_found - return {"errors": ["Replay file not found"]} path = assist.get_raw_mob_by_id(project_id=projectId, session_id=sessionId) if path is None: - return {"errors": ["Replay file not found"]} + return not_found return FileResponse(path=path, media_type="application/octet-stream") @@ -311,13 +314,16 @@ def get_live_session_replay_file(projectId: int, sessionId: Union[int, str], dependencies=[OR_scope(Permissions.assist_live, Permissions.session_replay, Permissions.dev_tools)]) def get_live_session_devtools_file(projectId: int, sessionId: Union[int, str], context: schemas.CurrentContext = Depends(OR_context)): - if isinstance(sessionId, str) or not sessions.session_exists(project_id=projectId, session_id=sessionId): - if isinstance(sessionId, str): - print(f"{sessionId} not a valid number.") - else: - print(f"{projectId}/{sessionId} not found in DB.") + not_found = {"errors": ["Devtools file not found"]} + if isinstance(sessionId, str): + print(f"{sessionId} not a valid number.") + return not_found + if not sessions.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in DB.") + if not assist.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in Assist.") + return not_found - return {"errors": ["Devtools file not found"]} path = assist.get_raw_devtools_by_id(project_id=projectId, session_id=sessionId) if path is None: return {"errors": ["Devtools file not found"]}