brainlet/api/v1/gateway/index.js

89 lines
3.3 KiB
JavaScript
Raw Normal View History

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) {
2020-11-16 22:08:23 +02:00
console.log('[E] [gateway] [handshake] User disconnected due to failed authentication');
socket.isConnected = false;
socket.disconnect();
socket.disconnect(true);
callback(new Error('ERR_GATEWAY_AUTH_FAIL'));
};
GatewayServer.prototype.eventSetup = function() {
this._gateway.use((socket, callback) => {
2020-11-16 22:08:23 +02:00
console.log('[*] [gateway] [handshake] User authentication attempt');
socket.isConnected = false;
setTimeout(() => {
if (socket.isConnected) return;
2020-11-16 22:08:23 +02:00
console.log('[*] [gateway] [handshake] User still not connected after timeout, removing...');
socket.disconnect();
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;
2020-11-16 22:08:23 +02:00
console.log(`[*] [gateway] [handshake] User ${data.username} has successfully authenticated`);
return callback();
});
});
this._gateway.on('connection', (socket) => {
2020-11-16 22:08:23 +02:00
console.log(`[*] [gateway] [handshake] User ${socket.username} connected, sending hello and waiting for yoo...`);
socket.emit('hello');
socket.once('yoo', () => {
2020-11-16 22:08:23 +02:00
console.log(`[*] [gateway] [handshake] Got yoo from ${socket.username}, connection is finally completed!`);
socket.isConnected = true;
2020-11-16 22:08:23 +02:00
socket.on('message', ({ categoryId, content }) => {
// TODO: URGENT: Check if the category exists and if the user has access to it (access coming soon)
socket.to(categoryId).emit('message', {
username: socket.username,
categoryId: categoryId,
content: content
});
});
socket.on('subscribe', (categories) => {
for (let v of categories) {
// TODO: URGENT: Check if the category exists and if the user has access to it (access coming soon)
socket.join(v);
}
});
});
});
};
module.exports = GatewayServer;