mirror of
https://github.com/IrosTheBeggar/mStream.git
synced 2025-10-27 07:31:02 +00:00
263 lines
6.0 KiB
JavaScript
263 lines
6.0 KiB
JavaScript
// Websocket Server
|
|
const WebSocketServer = require('ws').Server;
|
|
const fe = require('path');
|
|
const url = require('url');
|
|
|
|
|
|
|
|
|
|
|
|
// list of currently connected clients (users)
|
|
var clients = { };
|
|
// Any code in here will be limitted in functionality
|
|
var guests = { };
|
|
|
|
// Mao code to JWT
|
|
var codeTokenMap = { };
|
|
|
|
|
|
const allowedCommands = [
|
|
'next',
|
|
'previous',
|
|
'playPause',
|
|
'addSong',
|
|
'getPlaylist',
|
|
'removeSong',
|
|
];
|
|
const guestCommands = [
|
|
'addSong',
|
|
'getPlaylist'
|
|
];
|
|
|
|
|
|
|
|
var tokenFunction = function(){
|
|
return false;
|
|
}
|
|
|
|
|
|
exports.specialTokenCode = function(jwt){
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// This part is run after the login code
|
|
exports.setup = function(mstream, server, program){
|
|
|
|
|
|
var vcFunc = function(info, cb){
|
|
cb(true);
|
|
}
|
|
|
|
// If we are logging in
|
|
if(program.users){
|
|
const jwt = require('jsonwebtoken');
|
|
|
|
vcFunc = function (info, cb) {
|
|
console.log(url.parse(info.req.url, true).query.token);
|
|
|
|
var token;
|
|
|
|
// Tokens are attached as a GET param
|
|
try{
|
|
token = url.parse(info.req.url, true).query.token;
|
|
}catch(err){
|
|
cb(false, 401, 'Unauthorized');
|
|
return;
|
|
}
|
|
|
|
if (!token){
|
|
cb(false, 401, 'Unauthorized');
|
|
}
|
|
else {
|
|
jwt.verify(token, program.secret, function (err, decoded) {
|
|
if (err) {
|
|
cb(false, 401, 'Unauthorized');
|
|
} else {
|
|
// TODO: Verify user has no denied functions
|
|
|
|
// We are going to create a new JWT specifically for this session
|
|
var sendData = {
|
|
username: decoded.username,
|
|
vPath: decoded.vPath,
|
|
restrictedFunctions: ['/db/recursive-scan', '/saveplaylist', '/deleteplaylist', '/download'] // TODO: Should probably have more in here
|
|
}
|
|
|
|
info.req.jwt = jwt.sign(sendData, program.secret);
|
|
cb(true);
|
|
}
|
|
});
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const wss = new WebSocketServer({ server: server, verifyClient: vcFunc });
|
|
// This callback function is called every time someone
|
|
// tries to connect to the WebSocket server
|
|
// TODO: Add authentication step with jwt if necessary
|
|
// TODO: https://gist.github.com/jfromaniello/8418116
|
|
wss.on('connection', function(connection) {
|
|
|
|
// accept connection - you should check 'request.origin' to make sure that
|
|
// client is connecting from your website
|
|
console.log((new Date()) + ' Connection accepted.');
|
|
|
|
|
|
// Generate code and assure it doesn't exist
|
|
var code = createAccountNumber(10000);
|
|
var guestcode = createAccountNumber(10000);
|
|
|
|
|
|
// Handle code failures
|
|
if(code === false || guestcode === false){
|
|
connection.send(JSON.stringify( { error: 'Failed To Create Instance'} ));
|
|
return;
|
|
}
|
|
|
|
|
|
// Add code to clients object
|
|
clients[code] = connection;
|
|
// Connect guest code to standard code
|
|
guests[guestcode] = code;
|
|
|
|
|
|
// create JWT
|
|
// TODO: We need to put a expiration date on the token and refresh it regularly
|
|
var token = false;
|
|
if(connection.upgradeReq.jwt){
|
|
token = connection.upgradeReq.jwt;
|
|
codeTokenMap[code] = token;
|
|
codeTokenMap[guestcode] = token;
|
|
}
|
|
|
|
// Send Code
|
|
connection.send(JSON.stringify( { code: code, guestCode: guestcode, token: token} ));
|
|
|
|
// user sent some message
|
|
connection.on('message', function(message) {
|
|
// Send client code back
|
|
connection.send(JSON.stringify( { code: code, guestCode: guestcode} ));
|
|
});
|
|
|
|
|
|
// user disconnected
|
|
connection.on('close', function(connection) {
|
|
// Remove client from array
|
|
delete guests[guestcode];
|
|
delete clients[code];
|
|
|
|
if(codeTokenMap[code]){
|
|
delete codeTokenMap[code];
|
|
delete codeTokenMap[guestcode];
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
// Function for creating account numbers
|
|
function createAccountNumber(limit = 100000){
|
|
// TODO: Check that limit is reasonably sized integer
|
|
|
|
var n = 0;
|
|
while (true) {
|
|
code = Math.floor(Math.random() * (limit * 9)) + limit;
|
|
if(!(code in clients) && !(code in guests)){
|
|
break;
|
|
}
|
|
if(n === 10){
|
|
console.log('Failed to create ID for jukebox.');
|
|
// FIXME: Try again with a larger number size
|
|
return false;
|
|
}
|
|
n++;
|
|
}
|
|
|
|
return code;
|
|
}
|
|
|
|
|
|
|
|
// Send codes to client
|
|
mstream.post( '/jukebox/push-to-client', function(req, res){
|
|
// Get client id
|
|
var json = JSON.parse(req.body.json);
|
|
var clientCode = json.code;
|
|
var command = json.command;
|
|
|
|
|
|
// Check that code exists
|
|
if(!(clientCode in clients) && !(clientCode in guests)){
|
|
res.status(500).json({ error: 'Client code not found' });
|
|
return;
|
|
}
|
|
|
|
// MAke sure command is allowed
|
|
if(allowedCommands.indexOf(command) === -1){
|
|
res.status(500).json({ error: 'Command Not Recognized' });
|
|
return;
|
|
}
|
|
|
|
if(clientCode in guests){
|
|
// Check that command does not violate guest conditions
|
|
if(guestCommands.indexOf(command) === -1){
|
|
res.status(500).json({ error: 'The command is not allowed for guests' });
|
|
return;
|
|
}
|
|
|
|
clientCode = guests[clientCode];
|
|
}
|
|
|
|
// TODO: Handle extra data for Add File Commands
|
|
|
|
// Push commands to client
|
|
clients[clientCode].send(JSON.stringify({command:command}));
|
|
|
|
// Send confirmation back to user
|
|
res.json({ status: 'done' });
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
// This part is run before the login code
|
|
exports.setup2 = function(mstream, server, program){
|
|
|
|
mstream.post('/jukebox/does-code-exist', function(req, res){
|
|
console.log(req.body);
|
|
// Get client id
|
|
// const json = JSON.parse(req.body.data);
|
|
const clientCode = req.body.code;
|
|
|
|
var status;
|
|
|
|
// Check that code exists
|
|
if(!(clientCode in clients) && !(clientCode in guests)){
|
|
res.json({ status: false });
|
|
return;
|
|
}
|
|
|
|
// Get Token
|
|
var jwt = false;
|
|
if(codeTokenMap[clientCode]){
|
|
jwt = codeTokenMap[clientCode];
|
|
}
|
|
|
|
var guestStatus = (clientCode in guests);
|
|
res.json({ status: true, guestStatus: guestStatus, token: jwt });
|
|
});
|
|
|
|
}
|