forked from hippoz/brainlet
add basic gateway connection functionality
This commit is contained in:
parent
c293389359
commit
046b4d2b01
10 changed files with 261 additions and 16 deletions
|
@ -43,7 +43,8 @@ app.post('/category/create', [
|
|||
category: {
|
||||
title: category.title,
|
||||
creator: category.creator,
|
||||
posts: category.posts
|
||||
posts: category.posts,
|
||||
_id: category._id
|
||||
}
|
||||
});
|
||||
}, undefined, config.roleMap.USER));
|
||||
|
@ -86,7 +87,10 @@ app.post('/post/create', [
|
|||
|
||||
res.status(200).json({
|
||||
error: false,
|
||||
message: 'SUCCESS_POST_CREATED'
|
||||
message: 'SUCCESS_POST_CREATED',
|
||||
post: {
|
||||
_id: post._id
|
||||
}
|
||||
});
|
||||
}, undefined, config.roleMap.USER));
|
||||
|
||||
|
@ -102,6 +106,9 @@ app.get('/category/:category/info', [
|
|||
const categoryId = req.params.category;
|
||||
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) {
|
||||
res.status(404).json({
|
||||
error: true,
|
||||
|
@ -116,7 +123,9 @@ app.get('/category/:category/info', [
|
|||
category: {
|
||||
title: category.title,
|
||||
creator: category.creator,
|
||||
posts: category.posts
|
||||
posts: category.posts,
|
||||
users: users,
|
||||
usersListLimit: 50
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
|
69
api/v1/gateway/index.js
Normal file
69
api/v1/gateway/index.js
Normal 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;
|
|
@ -148,7 +148,8 @@ app.get('/current/info', authenticateEndpoint((req, res, user) => {
|
|||
username: user.username,
|
||||
email: user.email,
|
||||
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));
|
||||
|
|
16
apitest.rest
16
apitest.rest
|
@ -20,34 +20,34 @@ Content-Type: application/json
|
|||
###
|
||||
|
||||
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
|
||||
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDA1MTA2MTEsImV4cCI6MTYwMDUyMTQxMX0.q85p94FLPR4fxZ4O5pmalEEjU9Hyr9js63u6LgoCQCw
|
||||
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDU0ODI5NjgsImV4cCI6MTYwNTQ5Mzc2OH0.BjZEnI1v7XCYpEqyBub7uFrTtfQUZ7_PukP4sgcEzB0
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "testing1"
|
||||
"title": "testing1"
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
POST http://localhost:3000/api/v1/content/post/create
|
||||
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDA1MTA2MTEsImV4cCI6MTYwMDUyMTQxMX0.q85p94FLPR4fxZ4O5pmalEEjU9Hyr9js63u6LgoCQCw
|
||||
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDU0ODI5NjgsImV4cCI6MTYwNTQ5Mzc2OH0.BjZEnI1v7XCYpEqyBub7uFrTtfQUZ7_PukP4sgcEzB0
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"category": "5f65e1f05c3cdd86400f43ec",
|
||||
"category": "5fb1ba3eb04f2b3356aa2e58",
|
||||
"title": "Test title",
|
||||
"content": "Test content!!!"
|
||||
"body": "Test content!!!"
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
GET http://localhost:3000/api/v1/content/category/5f65e1f05c3cdd86400f43ec/info
|
||||
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDA1MTA2MTEsImV4cCI6MTYwMDUyMTQxMX0.q85p94FLPR4fxZ4O5pmalEEjU9Hyr9js63u6LgoCQCw
|
||||
GET http://localhost:3000/api/v1/content/category/5fb1ba3eb04f2b3356aa2e58/info
|
||||
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2MDU0ODI5NjgsImV4cCI6MTYwNTQ5Mzc2OH0.BjZEnI1v7XCYpEqyBub7uFrTtfQUZ7_PukP4sgcEzB0
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<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="/socket.io/socket.io.js"></script>
|
||||
<script defer src="./resources/js/app.js"></script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -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({
|
||||
el: '#app',
|
||||
data: {
|
||||
|
@ -93,7 +128,8 @@ const app = new Vue({
|
|||
_id: '',
|
||||
username: '',
|
||||
role: ''
|
||||
}
|
||||
},
|
||||
gateway: new GatewayConnection()
|
||||
},
|
||||
mounted: async function() {
|
||||
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) {
|
||||
this.loggedInUser = json.user;
|
||||
this.showApp = true;
|
||||
this.performGatewayConnection();
|
||||
this.browseCategories();
|
||||
} else {
|
||||
this.showApp = false;
|
||||
|
@ -153,6 +190,10 @@ const app = new Vue({
|
|||
this.snackbarNotification = text;
|
||||
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) {
|
||||
this.cardButtons.push({ text, click });
|
||||
},
|
||||
|
@ -320,6 +361,9 @@ const app = new Vue({
|
|||
this.resetSnackbarButton();
|
||||
this.notification('Failed to fetch category');
|
||||
}
|
||||
},
|
||||
openChatForCategory: async function(categoryId) {
|
||||
|
||||
},
|
||||
browseCategories: async function() {
|
||||
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.button('Chat', (post) => {
|
||||
this.browse(post);
|
||||
});
|
||||
this.button('View', (post) => {
|
||||
this.browse(post);
|
||||
});
|
||||
|
|
|
@ -10,5 +10,6 @@ module.exports = {
|
|||
'RESTRICTED': 1,
|
||||
'USER': 2,
|
||||
'ADMIN': 3
|
||||
}
|
||||
},
|
||||
gatewayStillNotConnectedTimeoutMS: 15*1000
|
||||
};
|
7
index.js
7
index.js
|
@ -4,10 +4,15 @@ const apiRoute = require('./api/v1');
|
|||
const express = require('express');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const cors = require('cors')
|
||||
const http = require('http');
|
||||
|
||||
const { authenticateEndpoint } = require('./api/v1/authfunctions');
|
||||
const GatewayServer = require('./api/v1/gateway/index');
|
||||
|
||||
const app = express();
|
||||
const httpServer = http.createServer(app);
|
||||
|
||||
const gateway = new GatewayServer(httpServer);
|
||||
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
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 musk’s 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 “you’re 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😘,i’m 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}`);
|
||||
});
|
111
package-lock.json
generated
111
package-lock.json
generated
|
@ -47,6 +47,11 @@
|
|||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"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": {
|
||||
"version": "5.0.0",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "0.0.1",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "1.0.3",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "3.0.3",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
"express-rate-limit": "^5.1.3",
|
||||
"express-validator": "^6.6.1",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mongoose": "^5.10.0"
|
||||
"mongoose": "^5.10.0",
|
||||
"socket.io": "^3.0.1"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue