Init WIP Bot

This commit is contained in:
Logan Cusano
2022-12-11 06:09:25 -05:00
parent f1f4cb7750
commit 4e1b82c557
43 changed files with 6766 additions and 0 deletions

48
Server/app.js Normal file
View File

@@ -0,0 +1,48 @@
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var nodesRouter = require('./routes/nodes');
var adminRouter = require('./routes/admin');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// Web Interface
app.use('/', indexRouter);
// Nodes API
app.use('/nodes', nodesRouter);
// Admin API
app.use('/admin', adminRouter);
// catch 404 and forward to error handler
app.use((req, res, next) => {
next(createError(404));
});
// error handler
app.use((err, req, res, next) => {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;

90
Server/bin/www Normal file
View File

@@ -0,0 +1,90 @@
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('server:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}

View File

@@ -0,0 +1,8 @@
const databaseConfig = {
database_host: '100.20.1.45',
database_user: 'DRB_CNC',
database_password: 'baMbC6IAl$Rn7$h0PS',
database_database: 'DRB_CNC'
}
module.exports = databaseConfig;

View File

@@ -0,0 +1,76 @@
const mysqlHander = require("../mysqlHandler");
const utils = require("../utils");
exports.listAllNodes = async (req, res) => {
mysqlHander.getAllNodes((allNodes) => {
res.status(200).json({
"nodes_online": allNodes
});
});
}
// Add a new node to the
exports.newNode = async (req, res) => {
if (!req.body.name) return res.send(400)
try {
// Try to add the new user with defaults if missing options
mysqlHander.addNewNode({
'name': req.body.name,
'ip': req.body.ip ?? null,
'port': req.body.port ?? null,
'location': req.body.location ?? null,
'nearbySystems': req.body.nearbySystems ?? null,
'online': req.body.online ?? 0
}, (queryResults) => {
// Send back a success if the user has been added and the ID for the client to keep track of
res.status(202).json({"nodeId": queryResults.insertId});
})
}
catch (err) {
// Catch any errors
if (err === "No name provided") {
return res.sendStatus(400);
}
else console.log(err)
return res.sendStatus(500);
}
}
// Get the known info for the node specified
exports.getNodeInfo = async (req, res) => {
if (!req.query.id) return res.status(400).json("No id specified");
mysqlHander.getNodeInfoFromId(req.query.id, (nodeInfo) => {
res.status(200).json(nodeInfo);
})
}
// Updates the information received from the client based on ID
exports.nodeCheckIn = async (req, res) => {
if (!req.body.id) return res.status(400).json("No id specified");
mysqlHander.getNodeInfoFromId(req.body.id, (nodeInfo) => {
let nodeObject = {};
// Convert the DB systems buffer to a JSON object to be worked with
nodeInfo.nearbySystems = utils.BufferToJson(nodeInfo.nearbySystems)
// Convert the online status to a boolean to be worked with
nodeInfo.online = nodeInfo.online !== 0;
if (req.body.name && req.body.name !== nodeInfo.name) nodeObject.name = req.body.name
if (req.body.ip && req.body.ip !== nodeInfo.ip) nodeObject.ip = req.body.ip
if (req.body.port && req.body.port !== nodeInfo.port) nodeObject.port = req.body.port
if (req.body.location && req.body.location !== nodeInfo.location) nodeObject.location = req.body.location
if (req.body.nearbySystems && JSON.stringify(req.body.nearbySystems) !== JSON.stringify(nodeInfo.nearbySystems)) nodeObject.nearbySystems = req.body.nearbySystems
if (req.body.online && req.body.online !== nodeInfo.online) nodeObject.online = req.body.online
// If no changes are made tell the client
if (Object.keys(nodeObject).length === 0) return res.status(200).json("No keys updated");
console.log("Updating the following keys for ID:", req.body.id, nodeObject);
// Adding the ID key to the body so that the client can double-check their ID
nodeObject.id = req.body.id;
mysqlHander.updateNodeInfo(nodeObject, () => {
return res.status(202).json({"updatedKeys": nodeObject});
})
})
}

121
Server/mysqlHandler.js Normal file
View File

@@ -0,0 +1,121 @@
const mysql = require('mysql');
const databaseConfig = require('./config/databaseConfig');
const utils = require('./utils');
const connection = mysql.createConnection({
host: databaseConfig.database_host,
user: databaseConfig.database_user,
password: databaseConfig.database_password,
database: databaseConfig.database_database
});
const nodesTable = `${databaseConfig.database_database}.nodes`;
connection.connect()
// Get all nodes the server knows about regardless of status
exports.getAllNodes = (callback) => {
const sqlQuery = `SELECT * FROM ${nodesTable}`
runSQL(sqlQuery, (rows) => {
callback(rows);
})
}
// Get all nodes that have the online status set true (are online)
exports.getOnlineNodes = (callback) => {
const sqlQuery = `SELECT * FROM ${nodesTable} WHERE online = 1;`
runSQL(sqlQuery, (rows) => {
callback(rows);
})
}
// Get info on a node based on ID
exports.getNodeInfoFromId = (nodeId, callback) => {
const sqlQuery = `SELECT * FROM ${nodesTable} WHERE id = ${nodeId}`
runSQL(sqlQuery, (rows) => {
// Call back the first (and theoretically only) row
// Specify 0 so downstream functions don't have to worry about it
callback(rows[0]);
})
}
// Add a new node to the DB
exports.addNewNode = (nodeObject, callback) => {
if (!nodeObject.name) throw new Error("No name provided");
const name = nodeObject.name,
ip = nodeObject.ip,
port = nodeObject.port,
location = nodeObject.location,
nearbySystems = utils.JsonToBuffer(nodeObject.nearbySystems),
online = nodeObject.online;
const sqlQuery = `INSERT INTO ${nodesTable} (name, ip, port, location, nearbySystems, online) VALUES ('${name}', '${ip}', ${port}, '${location}', '${nearbySystems}', ${online})`;
runSQL(sqlQuery, (rows) => {
callback(rows);
})
}
// Update the known info on a node
exports.updateNodeInfo = (nodeObject, callback) => {
const name = nodeObject.name,
ip = nodeObject.ip,
port = nodeObject.port,
location = nodeObject.location,
online = nodeObject.online;
let queryParams = [],
nearbySystems = nodeObject.nearbySystems;
if (name) queryParams.push(`name = '${name}'`);
if (ip) queryParams.push(`ip = '${ip}'`);
if (port) queryParams.push(`port = ${port}`);
if (location) queryParams.push(`location = '${location}'`);
if (nearbySystems) {
nearbySystems = utils.JsonToBuffer(nearbySystems)
queryParams.push(`nearbySystems = '${nearbySystems}'`);
}
if (typeof online === "boolean") {
if (online) queryParams.push(`online = 1`);
else queryParams.push(`online = 0`);
}
let sqlQuery = `UPDATE ${nodesTable} SET`
if (!queryParams || queryParams.length === 0) return callback(undefined);
if (queryParams.length === 1) {
sqlQuery = `${sqlQuery} ${queryParams[0]}`
} else {
let i = 0;
for (const param of queryParams) {
if (i === queryParams.length-1) {
sqlQuery = `${sqlQuery} ${param}`
i += 1;
}
else {
sqlQuery = `${sqlQuery} ${param},`
i += 1;
}
}
}
sqlQuery = `${sqlQuery} WHERE id = ${nodeObject.id};`
runSQL(sqlQuery, (rows) => {
if (rows.affectedRows === 1) callback(true);
else callback(rows);
})
}
// Function to run and handle SQL errors
function runSQL(sqlQuery, callback, error = (err) => {
console.log(err);
throw err;
}) {
connection.query(sqlQuery, (err, rows) => {
if (err) return error(err);
//console.log('The rows are:', rows);
return callback(rows);
})
}
exports.closeConnection = () => {
connection.end()
}

1071
Server/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

17
Server/package.json Normal file
View File

@@ -0,0 +1,17 @@
{
"name": "server",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"ejs": "~2.6.1",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"morgan": "~1.9.1",
"mysql": "^2.18.1"
}
}

View File

@@ -0,0 +1,8 @@
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}

16
Server/routes/admin.js Normal file
View File

@@ -0,0 +1,16 @@
var express = require('express');
var router = express.Router();
/* GET */
router.get('/', (req, res) => {
res.send('GET request to the admin')
})
/* POST */
router.post('/', (req, res) => {
console.log(req.body);
res.send('POST request to the post')
})
module.exports = router;

9
Server/routes/index.js Normal file
View File

@@ -0,0 +1,9 @@
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', (req, res, next) => {
res.render('index', { title: 'Express' });
});
module.exports = router;

31
Server/routes/nodes.js Normal file
View File

@@ -0,0 +1,31 @@
const express = require('express');
const router = express.Router();
const nodesController = require('../controllers/nodesController');
/* GET nodes the server knows */
router.get('/', nodesController.listAllNodes);
// TODO Need to authenticate this request
/* POST a new node to the server
*
* Will create a new DB entry for the node for the server to reference later
* Req. body: {
* "serverInfo": {"ip": "x.x.x.x", port: 0000}
* }
*
* Will return a token for the client to reference when the bot is making requests
* Res. body {
* "serverToken": ""
* }
*/
router.post('/newNode', nodesController.newNode);
// TODO Need to authenticate this request
/* GET the information the server has on a particular node */
router.get('/nodeInfo', nodesController.getNodeInfo);
// TODO Need to authenticate this request
// Client checkin with the server to update information
router.post('/nodeCheckIn', nodesController.nodeCheckIn);
module.exports = router;

9
Server/utils.js Normal file
View File

@@ -0,0 +1,9 @@
// Convert a JSON object to a buffer for the DB
exports.JsonToBuffer = (jsonObject) => {
return Buffer.from(JSON.stringify(jsonObject))
}
// Convert a buffer from the DB to JSON object
exports.BufferToJson = (buffer) => {
return JSON.parse(buffer.toString());
}

3
Server/views/error.ejs Normal file
View File

@@ -0,0 +1,3 @@
<h1><%= message %></h1>
<h2><%= error.status %></h2>
<pre><%= error.stack %></pre>

11
Server/views/index.ejs Normal file
View File

@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
</body>
</html>