add basic gateway connection functionality

This commit is contained in:
hippoz 2020-11-16 21:16:25 +02:00
parent c293389359
commit 046b4d2b01
10 changed files with 261 additions and 16 deletions

View file

@ -43,7 +43,8 @@ app.post('/category/create', [
category: { category: {
title: category.title, title: category.title,
creator: category.creator, creator: category.creator,
posts: category.posts posts: category.posts,
_id: category._id
} }
}); });
}, undefined, config.roleMap.USER)); }, undefined, config.roleMap.USER));
@ -86,7 +87,10 @@ app.post('/post/create', [
res.status(200).json({ res.status(200).json({
error: false, error: false,
message: 'SUCCESS_POST_CREATED' message: 'SUCCESS_POST_CREATED',
post: {
_id: post._id
}
}); });
}, undefined, config.roleMap.USER)); }, undefined, config.roleMap.USER));
@ -101,6 +105,9 @@ app.get('/category/:category/info', [
const categoryId = req.params.category; const categoryId = req.params.category;
const category = await Category.findById(categoryId).populate('posts.creator', 'username _id'); const category = await Category.findById(categoryId).populate('posts.creator', 'username _id');
// TODO: Implement subscribing to a channel and stuff
const users = await User.find().sort({ _id: -1 }).limit(50).select('username _id')
if (!category) { if (!category) {
res.status(404).json({ res.status(404).json({
@ -116,7 +123,9 @@ app.get('/category/:category/info', [
category: { category: {
title: category.title, title: category.title,
creator: category.creator, creator: category.creator,
posts: category.posts posts: category.posts,
users: users,
usersListLimit: 50
} }
}); });
})); }));

69
api/v1/gateway/index.js Normal file
View file

@ -0,0 +1,69 @@
const User = require('../../../models/User');
const secret = require('../../../secret');
const config = require('../../../config');
const jwt = require('jsonwebtoken');
const siolib = require('socket.io')
class GatewayServer {
constructor(httpServer) {
this._io = siolib(httpServer);
this._gateway = this._io.of('/gateway');
this.eventSetup();
}
}
GatewayServer.prototype.authDisconnect = function(socket, callback) {
socket.isConnected = false;
socket.disconnect(true);
callback(new Error('ERR_GATEWAY_AUTH_FAIL'));
};
GatewayServer.prototype.eventSetup = function() {
this._gateway.use((socket, callback) => {
console.log('[*] [gateway] User authentication attempt');
socket.isConnected = false;
setTimeout(() => {
console.log('[*] [gateway] User still not connected after timeout, removing...');
socket.disconnect(true);
}, config.gatewayStillNotConnectedTimeoutMS);
// TODO: Maybe passing the token in the query is not the best idea?
const token = socket.handshake.query.token;
if (!token) return this.authDisconnect(socket, callback);
jwt.verify(token, secret.jwtPrivateKey, {}, async (err, data) => {
if (err) return this.authDisconnect(socket, callback);
if (!data) return this.authDisconnect(socket, callback);
if (!data.username) return this.authDisconnect(socket, callback);
const user = await User.findByUsername(data.username);
if (!user) return this.authDisconnect(socket, callback);
let permissionLevel = config.roleMap[user.role];
if (!permissionLevel) {
permissionLevel = 0;
}
if (permissionLevel < config.roleMap.USER) return this.authDisconnect(socket, callback);
socket.username = data.username;
console.log(`[*] [gateway] User ${data.username} has successfully authenticated`);
return callback();
});
});
this._gateway.on('connection', (socket) => {
console.log(`[*] [gateway] User ${socket.username} connected, sending hello and waiting for yoo...`);
socket.emit('hello');
socket.once('yoo', () => {
console.log(`[*] [gateway] Got yoo from ${socket.username}, connection is finally completed!`);
socket.isConnected = true;
});
});
};
module.exports = GatewayServer;

View file

@ -148,7 +148,8 @@ app.get('/current/info', authenticateEndpoint((req, res, user) => {
username: user.username, username: user.username,
email: user.email, email: user.email,
role: user.role, role: user.role,
permissionLevel: config.roleMap[user.role] permissionLevel: config.roleMap[user.role],
token: req.cookies.token // TODO: Passing the token like this is *terribly* insecure
}, },
}); });
}, undefined, 0)); }, undefined, 0));

View file

@ -20,34 +20,34 @@ Content-Type: application/json
### ###
GET http://localhost:3000/api/v1/users/current/info GET http://localhost:3000/api/v1/users/current/info
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDA1MTA2MTEsImV4cCI6MTYwMDUyMTQxMX0.q85p94FLPR4fxZ4O5pmalEEjU9Hyr9js63u6LgoCQCw Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDU0ODI5NjgsImV4cCI6MTYwNTQ5Mzc2OH0.BjZEnI1v7XCYpEqyBub7uFrTtfQUZ7_PukP4sgcEzB0.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDA1MTA2MTEsImV4cCI6MTYwMDUyMTQxMX0.q85p94FLPR4fxZ4O5pmalEEjU9Hyr9js63u6LgoCQCw
### ###
POST http://localhost:3000/api/v1/content/category/create POST http://localhost:3000/api/v1/content/category/create
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDA1MTA2MTEsImV4cCI6MTYwMDUyMTQxMX0.q85p94FLPR4fxZ4O5pmalEEjU9Hyr9js63u6LgoCQCw Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDU0ODI5NjgsImV4cCI6MTYwNTQ5Mzc2OH0.BjZEnI1v7XCYpEqyBub7uFrTtfQUZ7_PukP4sgcEzB0
Content-Type: application/json Content-Type: application/json
{ {
"name": "testing1" "title": "testing1"
} }
### ###
POST http://localhost:3000/api/v1/content/post/create POST http://localhost:3000/api/v1/content/post/create
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDA1MTA2MTEsImV4cCI6MTYwMDUyMTQxMX0.q85p94FLPR4fxZ4O5pmalEEjU9Hyr9js63u6LgoCQCw Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDU0ODI5NjgsImV4cCI6MTYwNTQ5Mzc2OH0.BjZEnI1v7XCYpEqyBub7uFrTtfQUZ7_PukP4sgcEzB0
Content-Type: application/json Content-Type: application/json
{ {
"category": "5f65e1f05c3cdd86400f43ec", "category": "5fb1ba3eb04f2b3356aa2e58",
"title": "Test title", "title": "Test title",
"content": "Test content!!!" "body": "Test content!!!"
} }
### ###
GET http://localhost:3000/api/v1/content/category/5f65e1f05c3cdd86400f43ec/info GET http://localhost:3000/api/v1/content/category/5fb1ba3eb04f2b3356aa2e58/info
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDA1MTA2MTEsImV4cCI6MTYwMDUyMTQxMX0.q85p94FLPR4fxZ4O5pmalEEjU9Hyr9js63u6LgoCQCw Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDU0ODI5NjgsImV4cCI6MTYwNTQ5Mzc2OH0.BjZEnI1v7XCYpEqyBub7uFrTtfQUZ7_PukP4sgcEzB0
Content-Type: application/json Content-Type: application/json
### ###

View file

@ -11,6 +11,7 @@
<link rel="stylesheet" href="https://unpkg.com/vue-material/dist/theme/default-dark.css"> <link rel="stylesheet" href="https://unpkg.com/vue-material/dist/theme/default-dark.css">
<script defer src="https://unpkg.com/vue-material"></script> <script defer src="https://unpkg.com/vue-material"></script>
<script defer src="/socket.io/socket.io.js"></script>
<script defer src="./resources/js/app.js"></script> <script defer src="./resources/js/app.js"></script>
<style> <style>

View file

@ -53,6 +53,41 @@ const getCreateCategoryError = (json) => {
} }
} }
class GatewayConnection {
constructor() {
this.isConnected = false;
this.socket = null;
}
}
GatewayConnection.prototype.connect = function(token) {
console.log('[*] [gateway] [handshake] Trying to connect to gateway');
this.socket = io('/gateway', {
query: {
token
},
transports: ['websocket']
});
this.socket.on('hello', () => {
console.log('[*] [gateway] [handshake] Got hello from server, sending yoo...');
this.socket.emit('yoo');
});
this.socket.on('error', (e) => {
console.log('[E] [gateway] Gateway error', e);
this.isConnected = false;
});
this.socket.on('disconnectNotification', (e) => {
console.log('[E] [gateway] Received disconnect notfication', e);
this.isConnected = false;
});
this.socket.on('disconnect', (e) => {
console.log('[E] [gateway] Disconnected from gateway: ', e);
this.isConnected = false;
});
};
const app = new Vue({ const app = new Vue({
el: '#app', el: '#app',
data: { data: {
@ -93,7 +128,8 @@ const app = new Vue({
_id: '', _id: '',
username: '', username: '',
role: '' role: ''
} },
gateway: new GatewayConnection()
}, },
mounted: async function() { mounted: async function() {
const res = await fetch(`${window.location.origin}/api/v1/users/current/info`, { const res = await fetch(`${window.location.origin}/api/v1/users/current/info`, {
@ -109,6 +145,7 @@ const app = new Vue({
if (json.user.permissionLevel >= 1) { if (json.user.permissionLevel >= 1) {
this.loggedInUser = json.user; this.loggedInUser = json.user;
this.showApp = true; this.showApp = true;
this.performGatewayConnection();
this.browseCategories(); this.browseCategories();
} else { } else {
this.showApp = false; this.showApp = false;
@ -153,6 +190,10 @@ const app = new Vue({
this.snackbarNotification = text; this.snackbarNotification = text;
this.showSnackbarNotification = true; this.showSnackbarNotification = true;
}, },
performGatewayConnection: function() {
// TODO: again, the thing im doing with the token is not very secure, since its being sent by the current user info endpoint and is also being send through query parameters
this.gateway.connect(this.loggedInUser.token);
},
button: function(text, click) { button: function(text, click) {
this.cardButtons.push({ text, click }); this.cardButtons.push({ text, click });
}, },
@ -320,6 +361,9 @@ const app = new Vue({
this.resetSnackbarButton(); this.resetSnackbarButton();
this.notification('Failed to fetch category'); this.notification('Failed to fetch category');
} }
},
openChatForCategory: async function(categoryId) {
}, },
browseCategories: async function() { browseCategories: async function() {
const res = await fetch(`${window.location.origin}/api/v1/content/category/list?count=50`, { const res = await fetch(`${window.location.origin}/api/v1/content/category/list?count=50`, {
@ -340,6 +384,9 @@ const app = new Vue({
this.cardButtons = []; this.cardButtons = [];
this.button('Chat', (post) => {
this.browse(post);
});
this.button('View', (post) => { this.button('View', (post) => {
this.browse(post); this.browse(post);
}); });

View file

@ -10,5 +10,6 @@ module.exports = {
'RESTRICTED': 1, 'RESTRICTED': 1,
'USER': 2, 'USER': 2,
'ADMIN': 3 'ADMIN': 3
} },
gatewayStillNotConnectedTimeoutMS: 15*1000
}; };

View file

@ -4,10 +4,15 @@ const apiRoute = require('./api/v1');
const express = require('express'); const express = require('express');
const cookieParser = require('cookie-parser'); const cookieParser = require('cookie-parser');
const cors = require('cors') const cors = require('cors')
const http = require('http');
const { authenticateEndpoint } = require('./api/v1/authfunctions'); const { authenticateEndpoint } = require('./api/v1/authfunctions');
const GatewayServer = require('./api/v1/gateway/index');
const app = express(); const app = express();
const httpServer = http.createServer(app);
const gateway = new GatewayServer(httpServer);
app.use(express.urlencoded({ extended: false })); app.use(express.urlencoded({ extended: false }));
app.use(express.json()); app.use(express.json());
@ -28,6 +33,6 @@ app.get('/admin', (req, res) => {
res.send('Keanu chungus wholesome 100 reddit moment 😀i beat up a kid that said minecraft bad 😂and my doggo bit him so i gave him snaccos😉 and we watched pewdiepie together while in elon musks cyber truck 😳talking about how superior reddit memers are : “haha emojis bad” 😲i said and keanu reeves came outta nowhere and said “this is wholesome 100, updoot this wholesome boy” 😗so i got alot of updoots and edit: thanks for the gold kind stranger😣. but the kind stranger revealed himself to be baby yoda eating chiccy nuggies😨 and drinking choccy milk😎 so we went to the cinema to see our (communism funny) favorite movies avengers endgame😆 but then thor played fortnite and fortnite bad😡, so then i said “reality is often dissappointing” and then baby yoda replied r/unexpectedthanos and i replied by r/expectedthanos😖 for balance and then danny devito came to pick us up from the cinema😩 and all the insta normies and gay mods stood watching😵 ,as we,superior redditors went home with danny devito to suck on his magnum dong😫 but i said no homo and started sucking,not like those gay mods😮,then the next morning we woke up to MrBeast telling us to plant 69420 million trees😌, me, baby yoda and danny said nice, and then on our way to plant 69420 million trees😊 (nice) we saw a kid doing a tiktok so keanu reeves appeared and said “we have a kid to burn” and i replied “youre breathtaking”😄 so i said “i need a weapon” and baby yoda gave me an RPG so i blew the kid (DESTRUCTION 100)😎 and posted it on r/memes and r/dankmemes and r/pewdiepiesubmissions and got 1000000000 updoots😘,im sure pewds will give me a big pp, then we shat on emoji users😂😂 and started dreaming about girls that will never like me😢 and posted a lie on r/teenagers about how i got a GF after my doggo died by the hands of fortnite players😳 so i exploited his death for updoots😜, but i watched the sunset with the wholesome gang😁 (keanu,danny,Mrbeast, pewds, spongebob,stefan karl , bob ross, steve irwin, baby yoda and other artists that reddit exploits them) [Everyone liked that] WHOLESOME 100 REDDIT 100🤡'); res.send('Keanu chungus wholesome 100 reddit moment 😀i beat up a kid that said minecraft bad 😂and my doggo bit him so i gave him snaccos😉 and we watched pewdiepie together while in elon musks cyber truck 😳talking about how superior reddit memers are : “haha emojis bad” 😲i said and keanu reeves came outta nowhere and said “this is wholesome 100, updoot this wholesome boy” 😗so i got alot of updoots and edit: thanks for the gold kind stranger😣. but the kind stranger revealed himself to be baby yoda eating chiccy nuggies😨 and drinking choccy milk😎 so we went to the cinema to see our (communism funny) favorite movies avengers endgame😆 but then thor played fortnite and fortnite bad😡, so then i said “reality is often dissappointing” and then baby yoda replied r/unexpectedthanos and i replied by r/expectedthanos😖 for balance and then danny devito came to pick us up from the cinema😩 and all the insta normies and gay mods stood watching😵 ,as we,superior redditors went home with danny devito to suck on his magnum dong😫 but i said no homo and started sucking,not like those gay mods😮,then the next morning we woke up to MrBeast telling us to plant 69420 million trees😌, me, baby yoda and danny said nice, and then on our way to plant 69420 million trees😊 (nice) we saw a kid doing a tiktok so keanu reeves appeared and said “we have a kid to burn” and i replied “youre breathtaking”😄 so i said “i need a weapon” and baby yoda gave me an RPG so i blew the kid (DESTRUCTION 100)😎 and posted it on r/memes and r/dankmemes and r/pewdiepiesubmissions and got 1000000000 updoots😘,im sure pewds will give me a big pp, then we shat on emoji users😂😂 and started dreaming about girls that will never like me😢 and posted a lie on r/teenagers about how i got a GF after my doggo died by the hands of fortnite players😳 so i exploited his death for updoots😜, but i watched the sunset with the wholesome gang😁 (keanu,danny,Mrbeast, pewds, spongebob,stefan karl , bob ross, steve irwin, baby yoda and other artists that reddit exploits them) [Everyone liked that] WHOLESOME 100 REDDIT 100🤡');
}); });
app.listen(config.ports.mainServerPort, () => { httpServer.listen(config.ports.mainServerPort, () => {
console.log(`Main server is listening on port ${config.ports.mainServerPort}`); console.log(`Main server is listening on port ${config.ports.mainServerPort}`);
}); });

111
package-lock.json generated
View file

@ -47,6 +47,11 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
}, },
"base64id": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
},
"bcrypt": { "bcrypt": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz",
@ -121,6 +126,11 @@
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
}, },
"component-emitter": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
},
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -233,6 +243,45 @@
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
}, },
"engine.io": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-4.0.2.tgz",
"integrity": "sha512-sumdttqWLNjbuSMOSgDdL2xiEld9s5QZDk9VLyr4e28o+lzNNADhU3qpQDAY7cm2VZH0Otw/U0fL8mEjZ6kBMg==",
"requires": {
"accepts": "~1.3.4",
"base64id": "2.0.0",
"cookie": "~0.4.1",
"cors": "~2.8.5",
"debug": "~4.1.0",
"engine.io-parser": "~4.0.0",
"ws": "^7.1.2"
},
"dependencies": {
"cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}
}
},
"engine.io-parser": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.1.tgz",
"integrity": "sha512-v5aZK1hlckcJDGmHz3W8xvI3NUHYc9t8QtTbqdR5OaH3S9iJZilPubauOm+vLWOMMWzpE3hiq92l9lTAHamRCg=="
},
"escape-html": { "escape-html": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@ -1008,6 +1057,63 @@
"resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
"integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
}, },
"socket.io": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.0.1.tgz",
"integrity": "sha512-oVYbCQ4sCwm4wVi+f1bsE3YFXcvd6b4JjVP8D7IZnQqBeJOKX9XrdgJWSbXqBEqUXPY3jdTqb1M3s4KFTa/IHg==",
"requires": {
"accepts": "~1.3.4",
"base64id": "~2.0.0",
"debug": "~4.1.0",
"engine.io": "~4.0.0",
"socket.io-adapter": "~2.0.3",
"socket.io-parser": "~4.0.1"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}
}
},
"socket.io-adapter": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.0.3.tgz",
"integrity": "sha512-2wo4EXgxOGSFueqvHAdnmi5JLZzWqMArjuP4nqC26AtLh5PoCPsaRbRdah2xhcwTAMooZfjYiNVNkkmmSMaxOQ=="
},
"socket.io-parser": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.1.tgz",
"integrity": "sha512-5JfNykYptCwU2lkOI0ieoePWm+6stEhkZ2UnLDjqnE1YEjUlXXLd1lpxPZ+g+h3rtaytwWkWrLQCaJULlGqjOg==",
"requires": {
"component-emitter": "~1.3.0",
"debug": "~4.1.0"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}
}
},
"sparse-bitfield": { "sparse-bitfield": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
@ -1119,6 +1225,11 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}, },
"ws": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz",
"integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ=="
},
"yallist": { "yallist": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",

View file

@ -17,6 +17,7 @@
"express-rate-limit": "^5.1.3", "express-rate-limit": "^5.1.3",
"express-validator": "^6.6.1", "express-validator": "^6.6.1",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"mongoose": "^5.10.0" "mongoose": "^5.10.0",
"socket.io": "^3.0.1"
} }
} }