Database interaction and basic controller layout

This commit is contained in:
plane000
2018-08-19 17:39:55 +01:00
parent e975b34546
commit 8c73a65b29
13 changed files with 4420 additions and 13 deletions

4148
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,11 +7,15 @@
"body-parser": "^1.18.3",
"colors": "^1.3.1",
"express": "^4.16.3",
"json-stringify-safe": "^5.0.1",
"mysql": "^2.16.0",
"regenerator-runtime": "^0.12.1"
},
"devDependencies": {
"babel-preset-env": "^1.7.0",
"babel-register": "^6.26.0"
"babel-register": "^6.26.0",
"webpack": "^4.16.5",
"webpack-cli": "^3.1.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"

View File

@@ -1 +1,4 @@
# Install and create database script here, bash
# Users table structure CREATE TABLE `notes`.`Users` ( `id` bigint(20) NOT NULL, `username` text, `password` text, `email` text, `phone` text, `ip` text, `token` text, `lastupdated` text, `verified` tinyint(4) NOT NULL DEFAULT '0', `authcode` text, `timeauthed` text NOT NULL, `admin` tinyint(4) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `notes`.`Users` ADD PRIMARY KEY (`id`);

View File

@@ -1,14 +1,15 @@
import {Logger} from './models/logger';
import {Config} from './config/config'
import {DbTools} from './models/database/tools';
import {Server} from './server';
import {Router} from './controllers/routes/router';
init();
async function init() {
await Config.load();
await DbTools.connect();
await DbTools.testConnection();
await Server.start();
await Router.initEndpoints();
}

View File

@@ -3,18 +3,39 @@ import fs from 'fs';
import {Logger} from '../models/logger';
let server;
let database;
export class Config {
static get Server() {return server}
static get Database() {return database}
static async load() {
Logger.info('Loading config');
try {
let temp = fs.readFileSync('src/config/configs/server.json')
server = JSON.parse(temp);
if (!server.HTTPPort) throw new Error('ERROR LOADING: Server HTTP port not defined in: src/config/configs/server.json');
if (!server.SocketPort) throw new Error('ERROR LOADING: Server Socket port not defined in: src/config/configs/server.json');
Logger.info('LOADED: src/config/configs/server.json')
} catch (e) {
Logger.panic('ERROR LOADING: src/config/configs/server.json');
}
try {
let temp = fs.readFileSync('src/config/configs/database.json');
database = JSON.parse(temp);
if (!database.host) throw new Error('ERRROR LOADING: Database host not defined in: src/config/configs/database.json');
if (!database.user) throw new Error('ERRROR LOADING: Database user not defined in: src/config/configs/database.json');
if (!database.password) throw new Error('ERRROR LOADING: Database password not defined in: src/config/configs/database.json');
if (!database.database) throw new Error('ERRROR LOADING: Database database not defined in: src/config/configs/database.json');
Logger.info('LOADED: src/config/configs/database.json');
} catch (e) {
Logger.panic('ERROR LOADING: src/config/configs/database.json');
}
Logger.info('Config loaded');
}
}

View File

@@ -0,0 +1,6 @@
{
"host": "localhost",
"user": "root",
"password": "Plane101",
"database": "notes"
}

8
src/controllers/index.js Normal file
View File

@@ -0,0 +1,8 @@
import {Logger} from '../models/logger';
module.exports.Controller
Controller.UserController = () => {}
class ControllerHandler {}

View File

@@ -0,0 +1,15 @@
import stringify from 'json-stringify-safe';
import {Logger} from '../models/logger';
export class MiddleWare {
static analytics(req, res, next) {
// TODO: Send data such as IP to an anyaltitics model
Logger.info(`${req.method} request to ${req.url}`)
next();
}
static newUser(req, res, next) {
next();
}
}

View File

@@ -1,23 +1,26 @@
import {Logger} from '../../models/logger';
import {Server} from '../../server';
import {MiddleWare} from '../middleware';
import {StatusCodes} from '../status';
let app;
export class Router {
static async initEndpoints() {
Logger.info('Setting up API HTTP endpoints');
app = Server.App;
app.get('/', (req, res) => {
res.end('DEV SERVER');
});
app.get('/user/:id', (req, res) => {});
app.get('/', [MiddleWare.analytics, Router.frontPage]);
app.get('/user/:id', (req, res) => [MiddleWare.analytics, Controllers.getUser]);
app.delete('/user/:id', (req, res) => {});
app.post('/user', (req, res) => {});
app.use([MiddleWare.analytics, StatusCodes.pageNotFound]);
Logger.info('HTTP endpoints settup');
}
static frontPage(req, res, next) {
res.end('DEVELOPMENT SERVER');
}
}

View File

@@ -0,0 +1,5 @@
export class StatusCodes {
static pageNotFound(req, res) {
res.status(404).end('404 Page not found');
}
}

View File

@@ -0,0 +1,41 @@
import mysql from 'mysql';
import {Logger} from '../logger';
import {Config} from '../../config/config';
let connection;
export class Database {
static get Connection() {return connection}
static async connect() {
Logger.info('Connecting to mySQL database');
let promise = new Promise((resolve, reject) => {
connection = mysql.createConnection(Config.Database);
connection.connect((err) => {
if (err) {
Logger.panic('Failed to connect to the database as user ' + Config.Database.user);
reject();
}
Logger.info('Connected to mySQL as id ' + connection.threadId);
resolve();
});
});
await promise;
}
static async testConnection() {
let promise = new Promise((resolve, reject) => {
connection.query('SELECT 1 + 1 AS solution', async function (err, results, fields) {
if (err) {
Logger.panic('Failed to query the database');
reject();
}
Logger.info('Database connection tested and secure');
resolve();
});
});
await promise;
}
}

View File

@@ -0,0 +1,152 @@
import {Database} from './database';
import {Logger} from '../logger';
export class DbTools extends Database {
static async getRow(table, id) {
let connection = Database.Connection;
let res;
let promise = new Promise((resolve, reject) => {
connection.query(`SELECT * FROM \`${table}\` WHERE \`${table}\`.\`id\` = '${id}';`, async(err, results, fields) => {
if (err) {
Logger.warn(`Error querying ${table} with ${id}`);
return -1;
reject();
}
res = results;
resolve();
});
});
await promise;
if (res[0]) {
return res[0];
} else {
return -1;
}
}
static async getID(table, column, term) {
let connection = Database.Connection;
let res;
let promise = new Promise((resolve, reject) => {
connection.query(`SELECT \`id\` FROM \`${table}\` WHERE \`${table}\`.\`${column}\` = '${term}';`, async(err, results, fields) => {
if (err) {
Logger.warn(`Error querying ${table}'s ${column} with ${term}`);
return -1;
reject();
}
res = results;
resolve();
});
});
await promise;
let id = 0;
if (res[0]) {
id = res[0].id;
} else {
id = 0;
}
return id;
}
static async createUser(id, username, password, email, phone, ip, token, lastupdated, admin, authcode) {
let connection = Database.Connection;
let promise = new Promise((resolve, reject) => {
connection.query(`INSERT INTO \`Users\` (\`id\`, \`username\`, \`password\`, \`email\`, \`phone\`, \`ip\`, \`token\`, \`lastupdated\`, \`verified\`, \`authcode\`, \`timeauthed\`,\`admin\`) VALUES ('${id}', '${username}', '${password}', '${email}', '${phone}', '${ip}', '${token}', '${lastupdated}', '0', '${authcode}', 'UNAUTHORISED', '${admin}');` , async(err, results, fields) => {
if (err) {
Logger.warn(`Error inserting user ${username}`);
return -1;
reject();
}
resolve();
});
});
await promise;
}
static async deleteUser(id) {
let connection = Database.Connection;
let promise = new Promise((resolve, reject) => {
connection.query(`DELETE FROM \`Users\` WHERE \`id\` = '${id}'`, async(err, results, fields) => {
if(err) {
Logger.warn(`Error deleting User at ID ${id}`);
return -1;
reject();
}
resolve();
});
});
await promise;
return 1;
}
static async updateUserIP(id, ip) {
let connection = Database.Connection;
let promise = new Promise((resolve, reject) => {
connection.query(`UPDATE \`Users\` SET \`ip\` = '${ip}' WHERE \`Users\`.\`id\` = '${id}'`, async(err, results, fields) => {
if(err) {
Logger.warn(`Error updating User ip at ID ${id}`);
return -1;
reject();
}
resolve();
});
});
await promise;
return 1;
}
static async authUser(id, timeauthed) {
let connection = Database.Connection;
let promise = new Promise((resolve, reject) => {
connection.query(`UPDATE \`Users\` SET \`verified\` = '1' WHERE \`Users\`.\`id\` = '${id}'`, async(err, results, fields) => {
if(err) {
Logger.warn(`Error authorizing User at ID ${id}`);
return -1;
reject();
}
resolve();
});
});
await promise;
let promise1 = new Promise((resolve, reject) => {
connection.query(`UPDATE \`Users\` SET \`timeauthed\` = '${timeauthed}' WHERE \`Users\`.\`id\` = '${id}'`, async(err, results, fields) => {
if(err) {
Logger.warn(`Error authorizing User at ID ${id}`);
return -1;
reject();
}
resolve();
});
});
await promise1;
return 1;
}
static async exec(cmd) {
let connection = Database.Connection;
let res;
let promise = new Promise((resolve, reject) => {
connection.query(cmd, async(err, results, fields) => {
if (err) {
Logger.warn(`Error executing ${cmd} on the database`);
return -1;
reject();
}
res = results;
resolve();
})
});
await promise;
return res;
}
}

View File

@@ -18,9 +18,9 @@ export class Server {
Logger.info('Server created');
let port = Config.Server.HTTPPort;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
try {
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.listen(port);
} catch (e) {
Logger.panic(`Could not open a connection on port ${port}, maybe the port is populated or permissions are not met`);