Init WIP Bot
This commit is contained in:
48
Server/app.js
Normal file
48
Server/app.js
Normal 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
90
Server/bin/www
Normal 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);
|
||||
}
|
||||
8
Server/config/databaseConfig.js
Normal file
8
Server/config/databaseConfig.js
Normal 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;
|
||||
76
Server/controllers/nodesController.js
Normal file
76
Server/controllers/nodesController.js
Normal 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
121
Server/mysqlHandler.js
Normal 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
1071
Server/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
Server/package.json
Normal file
17
Server/package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
8
Server/public/stylesheets/style.css
Normal file
8
Server/public/stylesheets/style.css
Normal 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
16
Server/routes/admin.js
Normal 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
9
Server/routes/index.js
Normal 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
31
Server/routes/nodes.js
Normal 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
9
Server/utils.js
Normal 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
3
Server/views/error.ejs
Normal file
@@ -0,0 +1,3 @@
|
||||
<h1><%= message %></h1>
|
||||
<h2><%= error.status %></h2>
|
||||
<pre><%= error.stack %></pre>
|
||||
11
Server/views/index.ejs
Normal file
11
Server/views/index.ejs
Normal 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>
|
||||
Reference in New Issue
Block a user