mirror of
https://github.com/TheGreyDiamond/elevatormapRewritten.git
synced 2025-07-17 18:23:48 +02:00
333 lines
9.8 KiB
TypeScript
333 lines
9.8 KiB
TypeScript
// Imports
|
|
const express = require("express");
|
|
const fs = require("fs");
|
|
const Eta = require("eta");
|
|
const winston = require("winston");
|
|
const mysql = require("mysql");
|
|
const bodyParser = require("body-parser");
|
|
const session = require("express-session");
|
|
const nodemailer = require("nodemailer");
|
|
|
|
// Inting the logger
|
|
const logger = winston.createLogger({
|
|
level: "debug",
|
|
format: winston.format.json(),
|
|
defaultMeta: { service: "user-service" },
|
|
transports: [
|
|
//
|
|
// - Write all logs with level `error` and below to `error.log`
|
|
// - Write all logs with level `info` and below to `combined.log`
|
|
//
|
|
new winston.transports.File({ filename: "error.log", level: "error" }),
|
|
new winston.transports.File({ filename: "combined.log" }),
|
|
],
|
|
});
|
|
|
|
logger.add(
|
|
new winston.transports.Console({
|
|
format: winston.format.simple(),
|
|
})
|
|
);
|
|
|
|
const app = express();
|
|
|
|
const startUpTime = Math.floor(new Date().getTime() / 1000);
|
|
|
|
// Skeleton Variables
|
|
let fontawesomeKey = "";
|
|
let mapboxAccessToken = "";
|
|
let mysqlData = { "user": "", "password": "", "database": "", "allowCreation": false };
|
|
let mailConf = { "host": "", "port": 0, "username": "", "password": "" };
|
|
let serverAdress = "";
|
|
let cookieSecret = ""
|
|
let jsonConfigGlobal = {};
|
|
let port = 3000;
|
|
|
|
// Load config
|
|
try {
|
|
const data = fs.readFileSync("config/default.json", "utf8");
|
|
const jsonContent = JSON.parse(data);
|
|
let jsonConfig = jsonContent;
|
|
if (jsonContent.redirectConfig) {
|
|
const data = fs.readFileSync(
|
|
"config/" + jsonContent.redirectConfig,
|
|
"utf8"
|
|
);
|
|
jsonConfig = JSON.parse(data);
|
|
}
|
|
fontawesomeKey = jsonConfig.fontAwesome;
|
|
mapboxAccessToken = jsonConfig.mapboxAccessToken;
|
|
mysqlData = jsonConfig.mysql;
|
|
|
|
mailConf = jsonConfig.mail;
|
|
serverAdress = jsonConfig.serverAdress;
|
|
port = jsonConfig.port;
|
|
cookieSecret =
|
|
jsonConfig.cookieSecret || "saF0DSF65AS4DF0S4D6F0S54DF0Fad";
|
|
jsonConfigGlobal = jsonConfig;
|
|
} catch (error) {
|
|
logger.error(
|
|
"While reading the config an error occured. The error was: " + error
|
|
);
|
|
}
|
|
|
|
// Express (server) preperation
|
|
app.use(express.static("static"));
|
|
|
|
app.use(bodyParser.urlencoded({ extended: false }));
|
|
app.use(bodyParser.json());
|
|
app.use(session({ secret: cookieSecret }));
|
|
app.use(function (req, res, next) {
|
|
// PreShow Errorpage handler
|
|
const pathesWhichRequireDB = ["map", "login", "register"];
|
|
const pathesWhichRequireLogin = ["createElevator"];
|
|
const path = req.path
|
|
const pathesDes = path.split("/")
|
|
let requiresDB = false;
|
|
let requiresLogin = false;
|
|
let allowContinue = true;
|
|
console.log(pathesDes)
|
|
|
|
if (pathesWhichRequireLogin.indexOf(pathesDes[1]) > -1) {
|
|
requiresLogin = true;
|
|
}
|
|
|
|
if (pathesDes[1] == "api") {
|
|
requiresDB = true;
|
|
}
|
|
if (pathesWhichRequireDB.indexOf(pathesDes[1]) > -1) {
|
|
requiresDB = true;
|
|
}
|
|
|
|
if (requiresDB) {
|
|
if (!mysqlIsUpAndOkay) {
|
|
allowContinue = false;
|
|
const data = fs.readFileSync("templates/dbError.html", "utf8");
|
|
let displayText =
|
|
"This might be an artifact of a recent restart. Maybe wait a few minutes and reload this page.";
|
|
if (startUpTime + 60 <= Math.floor(new Date().getTime() / 1000)) {
|
|
displayText =
|
|
"The server failed to connect to the MySQL server. This means it was unable to load any data.";
|
|
}
|
|
if (mySQLstate == 1) {
|
|
displayText =
|
|
"There is a problem with the database servers setup. Please check the log for more info.";
|
|
}
|
|
|
|
res.send(
|
|
Eta.render(data, {
|
|
author: metainfo.author,
|
|
desc: metainfo.desc,
|
|
siteTitel: metainfo.sitePrefix + "Error",
|
|
fontawesomeKey: fontawesomeKey,
|
|
displayText: displayText,
|
|
})
|
|
);
|
|
}
|
|
}
|
|
|
|
if (requiresLogin) {
|
|
if (req.session.username == undefined) {
|
|
allowContinue = false;
|
|
const data = fs.readFileSync("templates/redirect.html", "utf8");
|
|
res.send(
|
|
Eta.render(data, {
|
|
author: metainfo.author,
|
|
desc: metainfo.desc,
|
|
siteTitel: metainfo.sitePrefix + "Redirect",
|
|
fontawesomeKey: fontawesomeKey,
|
|
url: "/login?r=" + path,
|
|
})
|
|
);
|
|
}
|
|
}
|
|
|
|
console.log('Time:', Date.now())
|
|
if (allowContinue) {
|
|
next()
|
|
} else {
|
|
console.log("Stopped further exec of route")
|
|
}
|
|
})
|
|
|
|
// Mail preperation
|
|
const transport = nodemailer.createTransport({
|
|
host: mailConf.host,
|
|
port: mailConf.port,
|
|
requireTLS: true,
|
|
secure: false,
|
|
debug: true,
|
|
disableFileAccess: true,
|
|
auth: {
|
|
user: mailConf.username,
|
|
pass: mailConf.password,
|
|
},
|
|
});
|
|
|
|
logger.info("Testing SMTP connection");
|
|
transport.verify(function (error) {
|
|
if (error) {
|
|
logger.error(error);
|
|
} else {
|
|
logger.info("SMPT server is ready to accept messages");
|
|
}
|
|
});
|
|
|
|
// Basic defines for html
|
|
const metainfo = {
|
|
author: "TheGreydiamond",
|
|
desc: "The Elevatormap. A map for elevator spotters!",
|
|
sitePrefix: "Elevatormap - "
|
|
}
|
|
|
|
let mysqlIsUpAndOkay = false;
|
|
let mySQLstate = 0; // 0 -> Default failure 1 -> Missing strucutre
|
|
|
|
|
|
|
|
// Prepare MYSQL
|
|
let con = mysql.createConnection({
|
|
host: "localhost",
|
|
user: mysqlData.user,
|
|
password: mysqlData.password,
|
|
database: mysqlData.database,
|
|
});
|
|
|
|
function checkIfMySQLStructureIsReady() {
|
|
if (mysqlIsUpAndOkay) {
|
|
// Only if MySQL is ready
|
|
logger.debug("Checking MySQL strucutre");
|
|
con.query("SHOW TABLES;", function (err, result, fields) {
|
|
if (err) throw err;
|
|
if (result.length == 0) {
|
|
// There are no tables. Not good.
|
|
logger.warn("There are no tables found");
|
|
if (mysqlData.allowCreation) {
|
|
// Lets create it then
|
|
logger.warn("Creating a new table");
|
|
const sql =
|
|
"CREATE TABLE `" +
|
|
mysqlData.database +
|
|
"`.`elevators` ( `id` INT NOT NULL AUTO_INCREMENT , `lat` FLOAT NOT NULL , `lng` FLOAT NOT NULL , `manufacturer` VARCHAR(512) NOT NULL , `modell` VARCHAR(512) NOT NULL , `info` VARCHAR(512) NOT NULL , `visitabilty` INT NOT NULL , `technology` INT NOT NULL , `images` JSON NOT NULL , `amountOfFloors` INT NOT NULL , `maxPassangers` INT NOT NULL , `maxWeight` INT NOT NULL , `creator` INT NOT NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB;";
|
|
const newSql =
|
|
"CREATE TABLE `" +
|
|
mysqlData.database +
|
|
"`.`users` ( `id` INT NOT NULL AUTO_INCREMENT , `email` VARCHAR(255) NOT NULL , `username` VARCHAR(255) NOT NULL , `passwordHash` VARCHAR(512) NOT NULL , `permLevel` INT NOT NULL DEFAULT '0' , `verificationState` INT NOT NULL DEFAULT '0' , PRIMARY KEY (`id`), UNIQUE KEY (`email`)) ENGINE = InnoDB;";
|
|
const newSqlMailVeri =
|
|
"CREATE TABLE `" +
|
|
mysqlData.database +
|
|
"`.`mailverification` ( `id` INT NOT NULL AUTO_INCREMENT , `targetMail` VARCHAR(512) NOT NULL , `userID` INT NOT NULL , `token` VARCHAR(255) NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB;";
|
|
con.query(sql, function (err, result) {
|
|
if (err) throw err;
|
|
logger.info("Table created");
|
|
});
|
|
|
|
con.query(newSql, function (err, result) {
|
|
if (err) throw err;
|
|
logger.info("Usertable created");
|
|
});
|
|
|
|
con.query(newSqlMailVeri, function (err, result) {
|
|
if (err) throw err;
|
|
logger.info("Email verification table created");
|
|
});
|
|
} else {
|
|
// We cannot do that. Welp.
|
|
logger.warn(
|
|
"MySQL tables are missing and the config denies creation of new ones."
|
|
);
|
|
mysqlIsUpAndOkay = false;
|
|
mySQLstate = 1;
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
logger.warn("Tried checking the tables even though MySQL wasn't ready.");
|
|
}
|
|
}
|
|
|
|
con.connect(function (err) {
|
|
if (err) {
|
|
mysqlIsUpAndOkay = false;
|
|
logger.error("Connction to MySQL failed");
|
|
console.log(err);
|
|
} else {
|
|
logger.info("Mysql is ready.");
|
|
mysqlIsUpAndOkay = true;
|
|
checkIfMySQLStructureIsReady();
|
|
}
|
|
});
|
|
|
|
// Routes
|
|
app.get("/", function (req, res) { // Index page
|
|
const data = fs.readFileSync("templates/index.html", "utf8");
|
|
res.send(
|
|
Eta.render(data, {
|
|
author: metainfo.author,
|
|
desc: metainfo.desc,
|
|
siteTitel: metainfo.sitePrefix + "Start",
|
|
fontawesomeKey: fontawesomeKey,
|
|
})
|
|
);
|
|
});
|
|
|
|
app.get("/map", function (req, res) { // Map page showing all elevators
|
|
const data = fs.readFileSync("templates/map.html", "utf8");
|
|
res.send(
|
|
Eta.render(data, {
|
|
author: metainfo.author,
|
|
desc: metainfo.desc,
|
|
siteTitel: metainfo.sitePrefix + "Map",
|
|
fontawesomeKey: fontawesomeKey,
|
|
mapboxAccessToken: mapboxAccessToken,
|
|
})
|
|
)
|
|
|
|
});
|
|
|
|
app.get("/createElevator", function (req, res) { // Page to create a new elvator
|
|
const data = fs.readFileSync("templates/createElevator.html", "utf8");
|
|
res.send(
|
|
Eta.render(data, {
|
|
author: metainfo.author,
|
|
desc: metainfo.desc,
|
|
siteTitel: metainfo.sitePrefix + "New elevator",
|
|
fontawesomeKey: fontawesomeKey,
|
|
mapboxAccessToken: mapboxAccessToken,
|
|
})
|
|
);
|
|
});
|
|
|
|
require('./routes/api.route.ts')(app, con, mysqlIsUpAndOkay, logger, metainfo);
|
|
require('./routes/debug.route.ts')(app, con, logger, metainfo);
|
|
require('./routes/auth.route.ts')(app, con, logger, metainfo, jsonConfigGlobal);
|
|
|
|
// Some loops for handeling stuff,
|
|
setInterval(() => {
|
|
if (mysqlIsUpAndOkay == false) { // SQL reconnect
|
|
logger.warn("Retrying to connect to MySQL");
|
|
con = mysql.createConnection({
|
|
host: "localhost",
|
|
user: mysqlData.user,
|
|
password: mysqlData.password,
|
|
database: mysqlData.database,
|
|
});
|
|
|
|
con.connect(function (err) {
|
|
if (err) {
|
|
mysqlIsUpAndOkay = false;
|
|
logger.error("Connction to MySQL failed");
|
|
console.log(err);
|
|
} else {
|
|
logger.info("Mysql is ready.");
|
|
mysqlIsUpAndOkay = true;
|
|
}
|
|
});
|
|
}
|
|
}, 60*1000); // Every minute
|
|
|
|
// App start
|
|
app.listen(port, () => {
|
|
logger.info(`Elevator map ready at http://localhost:${port}`);
|
|
});
|