diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..3f047cd
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,3 @@
+node_modules
+dist
+*.js
\ No newline at end of file
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..ac5a94d
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,16 @@
+{
+ "root": true,
+ "parser": "@typescript-eslint/parser",
+ "plugins": [
+ "@typescript-eslint"
+ ],
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/eslint-recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "rules": {
+ "@typescript-eslint/no-var-requires": 0
+ }
+
+ }
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 93040c6..3360f4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -105,3 +105,4 @@ typings/
testingDONOTCOMMITME.json
static/uploads/*
+index.js
diff --git a/index.js b/index.js
index cce3aee..77458fc 100644
--- a/index.js
+++ b/index.js
@@ -1,49 +1,93 @@
// 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 bcrypt = require("bcrypt");
-const { verify } = require("hcaptcha");
-const csp = require(`helmet`);
-const session = require("express-session");
-const nodemailer = require("nodemailer");
-const crypto = require("crypto");
-const multer = require("multer");
-const path = require("path");
-
-const upload = multer({ dest: "static/uploads/" });
-
+var express = require("express");
+var fs = require("fs");
+var Eta = require("eta");
+var winston = require("winston");
+var mysql = require("mysql");
+var bodyParser = require("body-parser");
+// const csp = require(`helmet`);
+var session = require("express-session");
+var 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" }),
- ],
+var 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();
-
+logger.add(new winston.transports.Console({
+ format: winston.format.simple()
+}));
+var app = express();
app.use(express.static("static"));
-
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
-
+app.use(function (req, res, next) {
+ var pathesWhichRequireDB = ["map", "login", "register"];
+ var pathesWhichRequireLogin = ["createElevator"];
+ var path = req.path;
+ var pathesDes = path.split("/");
+ var requiresDB = false;
+ var requiresLogin = false;
+ var 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;
+ var data = fs.readFileSync("templates/dbError.html", "utf8");
+ var 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) {
+ allowContinue = false;
+ var 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");
+ }
+});
/*
app.use(csp.contentSecurityPolicy({
useDefaults: true,
@@ -62,1138 +106,198 @@ app.use(csp.contentSecurityPolicy({
}))
*/
-
// Settings
-const port = 3000;
-const startUpTime = Math.floor(new Date().getTime() / 1000);
-const saltRounds = 10;
-
+var port = 3000;
+var startUpTime = Math.floor(new Date().getTime() / 1000);
+var fontawesomeKey = "";
+var mapboxAccessToken = "";
+var mysqlData = { "user": "", "password": "", "database": "", "allowCreation": false };
+var hCaptcha = { "sitekey": "", "secret": "" };
+var mailConf = { "host": "", "port": 0, "username": "", "password": "" };
+var serverAdress = "";
+var cookieSecret = "";
+var jsonConfigGlobal = {};
// 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);
- }
- var fontawesomeKey = jsonConfig.fontAwesome;
- var mapboxAccessToken = jsonConfig.mapboxAccessToken;
- var mysqlData = jsonConfig.mysql;
- var hCaptcha = jsonConfig.hCaptcha;
- var mailConf = jsonConfig.mail;
- var serverAdress = jsonConfig.serverAdress;
- var cookieSecret =
- jsonConfig.cookieSecret || "saF0DSF65AS4DF0S4D6F0S54DF0Fad";
-} catch (error) {
- logger.error(
- "While reading the config an error occured. The error was: " + error
- );
+ var data = fs.readFileSync("config/default.json", "utf8");
+ var jsonContent = JSON.parse(data);
+ var jsonConfig = jsonContent;
+ if (jsonContent.redirectConfig) {
+ var data_1 = fs.readFileSync("config/" + jsonContent.redirectConfig, "utf8");
+ jsonConfig = JSON.parse(data_1);
+ }
+ fontawesomeKey = jsonConfig.fontAwesome;
+ mapboxAccessToken = jsonConfig.mapboxAccessToken;
+ mysqlData = jsonConfig.mysql;
+ mailConf = jsonConfig.mail;
+ serverAdress = jsonConfig.serverAdress;
+ cookieSecret =
+ jsonConfig.cookieSecret || "saF0DSF65AS4DF0S4D6F0S54DF0Fad";
+ jsonConfigGlobal = jsonConfig;
+}
+catch (error) {
+ logger.error("While reading the config an error occured. The error was: " + error);
}
-
var transport = nodemailer.createTransport({
- host: mailConf.host,
- port: mailConf.port,
- requireTLS: true,
- secure: false,
- debug: true,
- disableFileAccess: true,
- //authMethod: "START TLS",
- auth: {
- user: mailConf.username,
- pass: mailConf.password,
- },
+ host: mailConf.host,
+ port: mailConf.port,
+ requireTLS: true,
+ secure: false,
+ debug: true,
+ disableFileAccess: true,
+ //authMethod: "START TLS",
+ auth: {
+ user: mailConf.username,
+ pass: mailConf.password
+ }
});
-
//let transporter = nodemailer.createTransport(transport)
//console.log(transport.host)
logger.info("Testing SMTP connection");
-transport.verify(function (error, success) {
- if (error) {
- logger.error(error);
- } else {
- logger.info("SMPT server is ready to accept messages");
- }
+transport.verify(function (error) {
+ if (error) {
+ logger.error(error);
+ }
+ else {
+ logger.info("SMPT server is ready to accept messages");
+ }
});
-
app.use(session({ secret: cookieSecret }));
-
// Basic defines for html
-const author = "TheGreydiamond";
-const desc = "The Elevatormap. A map for elevator spotters!";
-const sitePrefix = "Elevatormap - ";
-let mysqlIsUpAndOkay = false;
-let mySQLstate = 0; // 0 -> Default failure 1 -> Missing strucutre
-
+var metainfo = {
+ author: "TheGreydiamond",
+ desc: "The Elevatormap. A map for elevator spotters!",
+ sitePrefix: "Elevatormap - "
+};
+var mysqlIsUpAndOkay = false;
+var mySQLstate = 0; // 0 -> Default failure 1 -> Missing strucutre
// Prepare MYSQL
var con = mysql.createConnection({
- host: "localhost",
- user: mysqlData.user,
- password: mysqlData.password,
- database: mysqlData.database,
+ host: "localhost",
+ user: mysqlData.user,
+ password: mysqlData.password,
+ database: mysqlData.database
});
-
-// sendVerificationMail(2);
-function sendVerificationMail(userId) {
- // Query for the mail
- const stmt = "SELECT * FROM mailverification WHERE id=" + userId;
- con.query(stmt, function (err, result, fields) {
- if (err) throw err; // TODO proper error handling
- if (result.length == 0) {
- logger.warn(
- "sendVerificationMail failed because ID " + userId + " doesnt exist!"
- );
- } else {
- const emailContent =
- "Hi! \n You have created an account for the open elevator map. To finalize the process please verify your E-Mail adress. Use this link: http://" +
- serverAdress +
- "/verify/" +
- result[0].token;
- let info = transport.sendMail({
- from: '"Elevator map " <' + mailConf.username + ">", // sender address
- to: result[0].targetMail, // list of receivers
- subject: "[Elevator map] Please verify your Mailadress", // Subject line
- text: emailContent, // plain text body
- html: emailContent.replace("\n", "
"), // html body
- });
- }
-
- console.log(result);
- });
-
- /*
- let info = await transporter.sendMail({
- from: '"Elevator map " <' + mysqlData.username + '>', // sender address
- to: "bar@example.com, baz@example.com", // list of receivers
- subject: "Hello ✔", // Subject line
- text: "Hello world?", // plain text body
- html: "Hello world?", // html body
- });*/
-}
-
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) {
- const data = fs.readFileSync("templates/index.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Start",
- fontawesomeKey: fontawesomeKey,
- })
- );
-});
-
-app.post("/login", function (req, res) {
- const password = req.body.pass;
- const mail = req.body.email;
- var sess = req.session;
- console.log(req.body.pass);
-
- // Check if okay
- if (
- mail != undefined &&
- mail != "" &&
- password != undefined &&
- password != ""
- ) {
- const mailRegex =
- /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
- if (mailRegex.test(mail)) {
- const stmt = "SELECT * FROM users WHERE email='" + mail + "';";
- con.query(stmt, function (err, result, fields) {
- if (err) throw err; // TODO proper error page
- if (result.length == 0) {
- const data = fs.readFileSync("templates/login.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Ok",
- fontawesomeKey: fontawesomeKey,
- error: true,
- errorMessage: "This user does not exist!",
- })
- );
- } else {
- bcrypt.compare(
- password,
- result[0].passwordHash,
- function (error, response) {
- if (response) {
- // Login okay
- sess.username = result[0].username;
- sess.uid = String(result[0].id);
- sess.mail = result[0].email;
-
- const data = fs.readFileSync("templates/redirect.html", "utf8");
- if(req.query.r != undefined && req.query.r != ""){
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Ok",
- fontawesomeKey: fontawesomeKey,
- url: req.query.r,
- })
- );
-
- }else{
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Ok",
- fontawesomeKey: fontawesomeKey,
- url: "/profile",
- })
- );
+ 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");
+ var 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;";
+ var 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;";
+ var 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 {
- // Password falsch
- const data = fs.readFileSync("templates/login.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Ok",
- fontawesomeKey: fontawesomeKey,
- error: true,
- errorMessage: "The given password is wrong.",
- })
- );
- }
}
- );
- }
- });
- } else {
- const data = fs.readFileSync("templates/login.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Ok",
- fontawesomeKey: fontawesomeKey,
- error: true,
- errorMessage: "The given E-Mail is invalid.",
- })
- );
- }
- } else {
- logger.warn(
- "The login form did not sent all data. Dump: \n Password: " +
- password +
- " \n E-Mail: " +
- mail
- );
- const data = fs.readFileSync("templates/genericError.html", "utf8");
- var displayText = "The form did not sent all the information needed.";
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText: displayText,
- })
- );
- }
-});
-
-app.get("/login", function (req, res) {
- if (mysqlIsUpAndOkay) {
- const data = fs.readFileSync("templates/login.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Login",
- fontawesomeKey: fontawesomeKey,
- })
- );
- } else {
- const data = fs.readFileSync("templates/dbError.html", "utf8");
- var 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: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText: displayText,
- })
- );
- }
-});
-
-app.get("/profile", function (req, res) {
- if (mysqlIsUpAndOkay) {
- if (req.session.username != undefined) {
- var Hour = new Date().getHours();
- var greeting = "Good night, ";
- if (Hour > 18) {
- greeting = "Good evening, ";
- } else if (Hour > 13) {
- greeting = "Good afternoon, ";
- } else if (Hour > 5) {
- greeting = "Good morning, ";
- }
- greeting += req.session.username;
- const hash = crypto
- .createHash("md5")
- .update(req.session.mail.replace(" ", "").toLowerCase())
- .digest("hex");
- gravatarURL = "https://www.gravatar.com/avatar/" + hash;
- const data = fs.readFileSync("templates/profile.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Profile",
- fontawesomeKey: fontawesomeKey,
- greeting: greeting,
- gravatarURL: gravatarURL,
- })
- );
- } else {
- const data = fs.readFileSync("templates/redirect.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Profile",
- fontawesomeKey: fontawesomeKey,
- url: "/login",
- })
- );
- }
- } else {
- const data = fs.readFileSync("templates/dbError.html", "utf8");
- var 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: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText: displayText,
- })
- );
- }
-});
-
-app.get("/register", function (req, res) {
- if (mysqlIsUpAndOkay) {
- const data = fs.readFileSync("templates/register.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Register",
- fontawesomeKey: fontawesomeKey,
- sitekey: hCaptcha.sitekey,
- })
- );
- } else {
- const data = fs.readFileSync("templates/dbError.html", "utf8");
- var 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: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText: displayText,
- })
- );
- }
-});
-
-app.post("/register", function (req, res) {
- if (mysqlIsUpAndOkay) {
- var sess = req.session;
- var resu;
- verify(hCaptcha.secret, req.body["g-recaptcha-response"]).then(
- (data) => (resu = data)
- );
- /*.catch(setTimeout(() => {
- //if(resu.success == false){
- console.log("HERE");
- const data = fs.readFileSync("templates/genericError.html", "utf8");
- resu = "-1";
- con
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText: "There was an issue with the Captcha",
- })
- );
- //}
-
- }, 0)
- );*/
-
- if (req.body.pass == req.body.pass2) {
- const mailRegex =
- /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
- if (mailRegex.test(req.body.email)) {
- setTimeout(() => {
- console.log(resu);
- if (resu.success == true) {
- bcrypt.hash(req.body.pass, saltRounds, (err, hash) => {
- const data = fs.readFileSync(
- "templates/genericError.html",
- "utf8"
- );
- // SQL INSERT
-
- var stmt =
- "INSERT INTO users(email, username, passwordHash) VALUES(?, ?, ?)";
- var stmt2 =
- "INSERT INTO mailverification(targetMail, userID, token) VALUES(?, ?, ?)";
- crypto.randomBytes(48, function (err, buffer) {
- var token = buffer.toString("hex");
- con.query(
- stmt,
- [req.body.email, req.body.username, hash],
- (err, results1, fields) => {
- if (err) {
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText:
- "An error occured while creating your account.",
- })
- );
- return console.error(err.message);
- } else {
- // Create mail verification
- con.query(
- stmt2,
- [req.body.email, results1.insertId, token],
- (err, results, fields) => {
- if (err) {
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText:
- "An error occured while creating your account.",
- })
- );
- return console.error(err.message);
- } else {
- sess.username = req.body.username;
- sess.id = results1.insertId;
- sess.mail = req.body.email;
- // get inserted id
- logger.info("Inserted Id:" + results.insertId);
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText: "OK " + hash,
- })
- );
- sendVerificationMail(results.insertId);
- }
- }
- );
- }
- }
- );
- });
- });
- } else {
- const data = fs.readFileSync("templates/register.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Register",
- fontawesomeKey: fontawesomeKey,
- sitekey: hCaptcha.sitekey,
- error: true,
- errorMessage: "You failed the captcha, please try again.",
- })
- );
- }
- }, 200);
- } else {
- // Passwords don't match up
- const data = fs.readFileSync("templates/register.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Register",
- fontawesomeKey: fontawesomeKey,
- sitekey: hCaptcha.sitekey,
- error: true,
- errorMessage: "The E-Mail given is not valid",
- })
- );
- }
- } else {
- // Passwords don't match up
- const data = fs.readFileSync("templates/register.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Register",
- fontawesomeKey: fontawesomeKey,
- sitekey: hCaptcha.sitekey,
- error: true,
- errorMessage: "The password have to match up.",
- })
- );
- }
- } else {
- const data = fs.readFileSync("templates/dbError.html", "utf8");
- var 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: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText: displayText,
- })
- );
- }
-});
-
-// Routes
-app.get("/verify*", function (req, res) {
- console.log(req.url.split("/")[2]);
- const data = fs.readFileSync("templates/genericError.html", "utf8");
- const stmt = "SELECT * FROM mailverification WHERE token = ?;";
-
- con.query(stmt, [req.url.split("/")[2]], function (err, result, fields) {
- if (err) {
- res.status(404);
- res.send(
- JSON.stringify({ state: "Failed", message: "Database error occured" })
- );
- logger.error(err);
- } else {
- if (result.length == 0) {
- res.status(404);
- res.send(
- JSON.stringify({ state: "Failed", message: "Link already done" })
- );
- } else {
- console.log(result);
- res.status(200);
- stmt2 = "DELETE FROM mailverification WHERE id=?";
- console.log(result[0].id);
- con.query(stmt2, [result[0].id], function (err, result, fields) {
- // TODO handling of this
- //logger.debug(err)
- //console.log(result)
});
- stmt3 = "UPDATE users SET verificationState=1 WHERE email=?";
- con.query(
- stmt3,
- [result[0].targetMail],
- function (err, result, fields) {
- // TODO handling of this
- //logger.debug(err)
- //console.log(result)
- }
- );
- res.send(JSON.stringify({ state: "OK", message: "Done!" }));
- }
}
- });
-});
-
-app.get("/logout", function (req, res) {
- req.session.destroy();
- const data = fs.readFileSync("templates/redirect.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Logout",
- fontawesomeKey: fontawesomeKey,
- url: "/",
- })
- );
-});
-
-app.get("/debug/showSessionInfo", function (req, res) {
- res.send(JSON.stringify(req.session));
-});
-
-app.get("/map", function (req, res) {
- if (mysqlIsUpAndOkay) {
- const data = fs.readFileSync("templates/map.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Map",
- fontawesomeKey: fontawesomeKey,
- mapboxAccessToken: mapboxAccessToken,
- })
- );
- } else {
- const data = fs.readFileSync("templates/dbError.html", "utf8");
- var 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.";
+ else {
+ logger.warn("Tried checking the tables even though MySQL wasn't ready.");
}
- 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: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText: displayText,
- })
- );
- }
-});
-
-app.get("/createElevator", function (req, res) {
- if (mysqlIsUpAndOkay) {
-
- if (req.session.username != undefined) {
- const data = fs.readFileSync("templates/createElevator.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "New elevator",
- fontawesomeKey: fontawesomeKey,
- mapboxAccessToken: mapboxAccessToken,
- })
- );
- } else {
- const data = fs.readFileSync("templates/redirect.html", "utf8");
- res.send(
- Eta.render(data, {
- author: author,
- desc: desc,
- siteTitel: sitePrefix + "Profile",
- fontawesomeKey: fontawesomeKey,
- url: "/login?r=/createElevator",
- })
- );
- }
-
-
-
- } else {
- const data = fs.readFileSync("templates/dbError.html", "utf8");
- var 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: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText: displayText,
- })
- );
- }
-});
-
-app.get("/api/getElevators", function (req, res) {
- console.log(req.query);
- if (
- req.query.lan != undefined &&
- req.query.lat != undefined &&
- req.query.radius != undefined
- ) {
- // All parameters are there
- res.setHeader("Content-Type", "application/json");
- try {
- var lan = parseFloat(req.query.lan);
- var lat = parseFloat(req.query.lat);
- var radius = parseFloat(req.query.radius);
- } catch (error) {
- res.send(
- JSON.stringify({ state: "Failed", message: "Invalid arguments" })
- );
- res.status(400);
- return;
- }
- var lan = parseFloat(req.query.lan);
- var lat = parseFloat(req.query.lat);
- var radius = parseFloat(req.query.radius);
-
- // TODO: Return just the elevators in the viewers area
-
- con.query("SELECT * FROM elevators", function (err, result, fields) {
- if (err) {
- res.status(500);
- res.send(
- JSON.stringify({
- state: "Failed",
- message: "A server side error occured.",
- results: [],
- })
- );
- logger.error("The server failed to execute a request");
- mysqlIsUpAndOkay = false;
- } else {
- console.log(result[0]);
- res.status(200);
- res.send(JSON.stringify({ state: "Ok", message: "", results: result }));
- }
- });
- } else {
- // Welp something is missing
- res.status(400);
- res.setHeader("Content-Type", "application/json");
- res.send(JSON.stringify({ state: "Failed", message: "Missing arguments" }));
- }
-});
-
-app.post("/api/uploadImage", upload.any(), function (req, res) {
- //TODO: Fix file ending, add image to elevator in DBw
- console.log(req.query.id)
- i = 0;
- const sql = 'SELECT id, images FROM elevators WHERE id=?';
- // req.query.id
- allImages = []
- while (i < req.files.length) {
- fObj = req.files[i];
- const currentPath = path.join(fObj["path"]);
- const destinationPath =
- currentPath +
- "." +
- fObj["originalname"].split(".")[
- fObj["originalname"].split(".").length - 1
- ]; // Add the file end
-
- fs.rename(currentPath, destinationPath, function (err) {
- if (err) {
- throw err;
- } else {
- console.log("Successfully moved the file!");
- }
- });
- allImages.push({"path": destinationPath, "alt": "No alt was provided."})
- i++;
- }
-
- con.query(
- sql, [req.query.id],
- function (err, result, fields) {
- if (err) {
- res.status(500);
- res.send(
- JSON.stringify({
- state: "Failed",
- message: "A server side error occured.",
- results: [],
- })
- );
- logger.error("The server failed to execute a request");
- mysqlIsUpAndOkay = false;
- } else {
- jData = JSON.parse(result[0].images)
- console.log(jData)
- jData.images.push.apply(jData.images, allImages)
- console.log(jData);
- console.log(result);
- var sql = "UPDATE elevators SET images = ? WHERE id = ?";
- con.query(sql, [JSON.stringify(jData), req.query.id], function(err, result, fields){
- if (err) {
- console.log("Update failure")
- }else{
- console.log("Okay")
- }
-
- })
- }
- }
- );
-
- // Save Image End
-});
-
-// returns an object with the cookies' name as keys
-const getAppCookies = (req) => {
- // We extract the raw cookies from the request headers
- const rawCookies = req.headers.cookie.split("; ");
- // rawCookies = ['myapp=secretcookie, 'analytics_cookie=beacon;']
-
- const parsedCookies = {};
- rawCookies.forEach((rawCookie) => {
- const parsedCookie = rawCookie.split("=");
- // parsedCookie = ['myapp', 'secretcookie'], ['analytics_cookie', 'beacon']
- parsedCookies[parsedCookie[0]] = parsedCookie[1];
- });
- return parsedCookies;
-};
-
-app.post("/api/saveNewElevatorMeta", function (req, res) {
- var sess = req.session;
- console.log(req.headers.cookie);
- tempJs = JSON.parse(decodeURIComponent(getAppCookies(req, res)["tempStore"]));
- console.log(tempJs);
- const sql =
- "INSERT INTO elevators (lat, lng, manufacturer, modell, info, visitabilty, technology, amountOfFloors, maxPassangers, maxWeight, images, creator) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '{ \"images\": []}', ?)";
- con.query(
- sql,
- [
- tempJs.lat,
- tempJs.lng,
- tempJs.manuf,
- tempJs.model,
- tempJs.description,
- tempJs.visit,
- tempJs.type,
- tempJs.flor,
- tempJs.pepl,
- tempJs.weig,
- sess.uid
- ],
- function (err, result) {
- if (err) throw err;
- console.log("1 record inserted with id " + result.insertId);
- res.setHeader("Content-Type", "application/json");
-
- res.send(
- JSON.stringify({ state: "Okay", message: "Ok. No fault!", id: result.insertId })
- );
- res.status(200);
- }
- );
-});
-
-app.get("/api/getElevatorLocation", function (req, res) {
- if (
- req.query.lan != undefined &&
- req.query.lat != undefined &&
- req.query.radius != undefined
- ) {
- // All parameters are there
- res.setHeader("Content-Type", "application/json");
- try {
- var lan = parseFloat(req.query.lan);
- var lat = parseFloat(req.query.lat);
- var radius = parseFloat(req.query.radius);
- } catch (error) {
- res.send(
- JSON.stringify({ state: "Failed", message: "Invalid arguments" })
- );
- res.status(400);
- return;
- }
- var lan = parseFloat(req.query.lan);
- var lat = parseFloat(req.query.lat);
- var radius = parseFloat(req.query.radius);
-
- // TODO: Return just the elevators in the viewers area
-
- con.query(
- "SELECT id, lat, lng FROM elevators",
- function (err, result, fields) {
- if (err) {
- res.status(500);
- res.send(
- JSON.stringify({
- state: "Failed",
- message: "A server side error occured.",
- results: [],
- })
- );
- logger.error("The server failed to execute a request");
- mysqlIsUpAndOkay = false;
- } else {
- console.log(result[0]);
- res.status(200);
- res.send(
- JSON.stringify({ state: "Ok", message: "", results: result })
- );
- }
- }
- );
- } else {
- // Welp something is missing
- res.status(400);
- res.setHeader("Content-Type", "application/json");
- res.send(JSON.stringify({ state: "Failed", message: "Missing arguments" }));
- }
-});
-
-app.get("/api/resolveNameById", function (req, res) {
- if (mysqlIsUpAndOkay) {
- if(req.query.id != undefined && req.query.id != ""){
-
- const sql = "SELECT username FROM users WHERE id=?";
- con.query(sql, [req.query.id], function (err, result, fields) {
- if (err) {
- res.status(500);
- res.send(
- JSON.stringify({
- state: "Failed",
- message: "A server side error occured.",
- results: [],
- })
- );
- logger.error("The server failed to execute a request");
- mysqlIsUpAndOkay = false;
- } else {
- console.log(result[0]);
- res.status(200);
- res.setHeader("Content-Type", "application/json");
- res.send(
- JSON.stringify({ state: "Ok", message: "", results: result })
- );
- }
- }
- );
- }else{
- res.status(400);
- res.setHeader("Content-Type", "application/json");
- res.send(JSON.stringify({ state: "Failed", message: "Missing argument: id" }));
- }
- } else {
- const data = fs.readFileSync("templates/dbError.html", "utf8");
- var 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: author,
- desc: desc,
- siteTitel: sitePrefix + "Error",
- fontawesomeKey: fontawesomeKey,
- displayText: displayText,
- })
- );
- }
-});
-
-app.get("/api/getElevatorById", function (req, res) {
- console.log(req.query);
- if (req.query.id != undefined) {
- // All parameters are there
- res.setHeader("Content-Type", "application/json");
- try {
- var id = parseFloat(req.query.id);
- } catch (error) {
- res.send(
- JSON.stringify({ state: "Failed", message: "Invalid arguments" })
- );
- res.status(400);
- return;
- }
- var id = parseFloat(req.query.id);
-
- con.query(
- "SELECT * FROM elevators WHERE id=" + id,
- function (err, result, fields) {
- if (err) {
- res.status(500);
- res.send(
- JSON.stringify({
- state: "Failed",
- message: "A server side error occured.",
- results: [],
- })
- );
- logger.error("The server failed to execute a request");
- console.log(err);
- mysqlIsUpAndOkay = false;
- } else {
- console.log(result[0]);
- res.status(200);
- res.send(
- JSON.stringify({
- state: "Ok",
- message: "Successful.",
- results: result,
- })
- );
- }
- }
- );
- } else {
- // Welp something is missing
- res.status(400);
- res.setHeader("Content-Type", "application/json");
- res.send(JSON.stringify({ state: "Failed", message: "Missing arguments" }));
- }
-});
-
-// Some loops for handeling stuff
-setInterval(() => {
- if (mysqlIsUpAndOkay == false) {
- 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) {
+}
+con.connect(function (err) {
+ if (err) {
mysqlIsUpAndOkay = false;
logger.error("Connction to MySQL failed");
console.log(err);
- } else {
+ }
+ else {
logger.info("Mysql is ready.");
mysqlIsUpAndOkay = true;
- }
- });
- }
-}, 60000);
-
-// App start
-app.listen(port, () => {
- logger.info(`Elevator map ready at http://localhost:${port}`);
+ checkIfMySQLStructureIsReady();
+ }
+});
+// Routes
+app.get("/", function (req, res) {
+ var 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) {
+ var 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) {
+ var 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(function () {
+ if (mysqlIsUpAndOkay == false) {
+ 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;
+ }
+ });
+ }
+}, 60000);
+// App start
+app.listen(port, function () {
+ logger.info("Elevator map ready at http://localhost:" + port);
});
diff --git a/index.ts b/index.ts
new file mode 100644
index 0000000..4f3d201
--- /dev/null
+++ b/index.ts
@@ -0,0 +1,357 @@
+// 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 csp = require(`helmet`);
+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();
+
+app.use(express.static("static"));
+
+app.use(bodyParser.urlencoded({ extended: false }));
+app.use(bodyParser.json());
+
+app.use(function (req, res, next) {
+ 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) {
+ 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")
+ }
+
+})
+
+/*
+app.use(csp.contentSecurityPolicy({
+ useDefaults: true,
+ contentSecurityPolicy: false,
+ crossOriginEmbedderPolicy: false,
+ directives: {
+ "default-src": [`'self'`],
+ "img-src": [`'self'`],
+ scriptSrc: [`'self'`, `https://hcaptcha.com`, `https://*.hcaptcha.com`, `https://*.fontawesome.com`, "unsafe-inline", "unsafe-eval","'unsafe-inline'"],
+ "script-src-attr": [`'self'`, `https://hcaptcha.com`, `https://*.hcaptcha.com`, `https://*.fontawesome.com`, "unsafe-inline", "unsafe-eval"],
+ "frame-src": [`'self'`, `https://hcaptcha.com`, `https://*.hcaptcha.com`],
+ "style-src": [`'self'`, `https://hcaptcha.com`, `https://*.hcaptcha.com`, `https://*.fontawesome.com`, `'unsafe-inline'`],
+ "connect-src": [`'self'`, `https://hcaptcha.com`, `https://*.hcaptcha.com`, `https://*.fontawesome.com`],
+ "font-src": [`'self'`, `https://*.fontawesome.com`],
+ },
+
+}))
+*/
+
+// Settings
+const port = 3000;
+const startUpTime = Math.floor(new Date().getTime() / 1000);
+
+
+let fontawesomeKey = "";
+let mapboxAccessToken = "";
+let mysqlData = { "user": "", "password": "", "database": "", "allowCreation": false };
+let hCaptcha = { "sitekey": "", "secret": "" };
+let mailConf = { "host": "", "port": 0, "username": "", "password": "" };
+let serverAdress = "";
+let cookieSecret = ""
+let jsonConfigGlobal = {};
+
+// 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;
+ cookieSecret =
+ jsonConfig.cookieSecret || "saF0DSF65AS4DF0S4D6F0S54DF0Fad";
+ jsonConfigGlobal = jsonConfig;
+} catch (error) {
+ logger.error(
+ "While reading the config an error occured. The error was: " + error
+ );
+}
+
+const transport = nodemailer.createTransport({
+ host: mailConf.host,
+ port: mailConf.port,
+ requireTLS: true,
+ secure: false,
+ debug: true,
+ disableFileAccess: true,
+ //authMethod: "START TLS",
+ auth: {
+ user: mailConf.username,
+ pass: mailConf.password,
+ },
+});
+
+//let transporter = nodemailer.createTransport(transport)
+//console.log(transport.host)
+logger.info("Testing SMTP connection");
+transport.verify(function (error) {
+ if (error) {
+ logger.error(error);
+ } else {
+ logger.info("SMPT server is ready to accept messages");
+ }
+});
+
+app.use(session({ secret: cookieSecret }));
+
+
+// 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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;
+ }
+ });
+ }
+}, 60000);
+
+// App start
+app.listen(port, () => {
+ logger.info(`Elevator map ready at http://localhost:${port}`);
+});
diff --git a/package-lock.json b/package-lock.json
index ae18b2f..a2df481 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4,6 +4,51 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+ "@babel/code-frame": {
+ "version": "7.12.11",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+ "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
+ "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
+ "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.14.5",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ }
+ }
+ },
"@dabh/diagnostics": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz",
@@ -14,6 +59,80 @@
"kuler": "^2.0.0"
}
},
+ "@eslint/eslintrc": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz",
+ "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.1.1",
+ "espree": "^7.3.0",
+ "globals": "^13.9.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^3.13.1",
+ "minimatch": "^3.0.4",
+ "strip-json-comments": "^3.1.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
+ "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
+ "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==",
+ "dev": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^1.2.0",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
+ "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@humanwhocodes/object-schema": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz",
+ "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==",
+ "dev": true
+ },
"@mapbox/node-pre-gyp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz",
@@ -30,6 +149,177 @@
"tar": "^6.1.0"
}
},
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz",
+ "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@types/json-schema": {
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
+ "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.0.tgz",
+ "integrity": "sha512-TmCW5HoZ2o2/z2EYi109jLqIaPIi9y/lc2LmDCWzuCi35bcaQ+OtUh6nwBiFK7SOu25FAU5+YKdqFZUwtqGSdg==",
+ "dev": true
+ },
+ "@typescript-eslint/eslint-plugin": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.2.tgz",
+ "integrity": "sha512-PGqpLLzHSxq956rzNGasO3GsAPf2lY9lDUBXhS++SKonglUmJypaUtcKzRtUte8CV7nruwnDxtLUKpVxs0wQBw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/experimental-utils": "4.28.2",
+ "@typescript-eslint/scope-manager": "4.28.2",
+ "debug": "^4.3.1",
+ "functional-red-black-tree": "^1.0.1",
+ "regexpp": "^3.1.0",
+ "semver": "^7.3.5",
+ "tsutils": "^3.21.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
+ "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@typescript-eslint/experimental-utils": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.2.tgz",
+ "integrity": "sha512-MwHPsL6qo98RC55IoWWP8/opTykjTp4JzfPu1VfO2Z0MshNP0UZ1GEV5rYSSnZSUI8VD7iHvtIPVGW5Nfh7klQ==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.7",
+ "@typescript-eslint/scope-manager": "4.28.2",
+ "@typescript-eslint/types": "4.28.2",
+ "@typescript-eslint/typescript-estree": "4.28.2",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^3.0.0"
+ }
+ },
+ "@typescript-eslint/parser": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.2.tgz",
+ "integrity": "sha512-Q0gSCN51eikAgFGY+gnd5p9bhhCUAl0ERMiDKrTzpSoMYRubdB8MJrTTR/BBii8z+iFwz8oihxd0RAdP4l8w8w==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/scope-manager": "4.28.2",
+ "@typescript-eslint/types": "4.28.2",
+ "@typescript-eslint/typescript-estree": "4.28.2",
+ "debug": "^4.3.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
+ "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@typescript-eslint/scope-manager": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.2.tgz",
+ "integrity": "sha512-MqbypNjIkJFEFuOwPWNDjq0nqXAKZvDNNs9yNseoGBB1wYfz1G0WHC2AVOy4XD7di3KCcW3+nhZyN6zruqmp2A==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.28.2",
+ "@typescript-eslint/visitor-keys": "4.28.2"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.2.tgz",
+ "integrity": "sha512-Gr15fuQVd93uD9zzxbApz3wf7ua3yk4ZujABZlZhaxxKY8ojo448u7XTm/+ETpy0V0dlMtj6t4VdDvdc0JmUhA==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.2.tgz",
+ "integrity": "sha512-86lLstLvK6QjNZjMoYUBMMsULFw0hPHJlk1fzhAVoNjDBuPVxiwvGuPQq3fsBMCxuDJwmX87tM/AXoadhHRljg==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.28.2",
+ "@typescript-eslint/visitor-keys": "4.28.2",
+ "debug": "^4.3.1",
+ "globby": "^11.0.3",
+ "is-glob": "^4.0.1",
+ "semver": "^7.3.5",
+ "tsutils": "^3.21.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
+ "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.2.tgz",
+ "integrity": "sha512-aT2B4PLyyRDUVUafXzpZFoc0C9t0za4BJAKP5sgWIhG+jHECQZUEjuQSCIwZdiJJ4w4cgu5r3Kh20SOdtEBl0w==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.28.2",
+ "eslint-visitor-keys": "^2.0.0"
+ }
+ },
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@@ -44,6 +334,18 @@
"negotiator": "0.6.2"
}
},
+ "acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
+ "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
+ "dev": true
+ },
"agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -67,11 +369,38 @@
}
}
},
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true
+ },
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
"append-field": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
@@ -115,11 +444,32 @@
}
}
},
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true
+ },
"async": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
@@ -170,6 +520,15 @@
"concat-map": "0.0.1"
}
},
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
@@ -212,6 +571,63 @@
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
},
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
+ "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
"chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
@@ -340,6 +756,17 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -348,6 +775,12 @@
"ms": "2.0.0"
}
},
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@@ -400,11 +833,35 @@
}
}
},
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
"enabled": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
@@ -415,15 +872,235 @@
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
+ "enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^4.1.1"
+ }
+ },
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true
+ },
+ "eslint": {
+ "version": "7.30.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.30.0.tgz",
+ "integrity": "sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "7.12.11",
+ "@eslint/eslintrc": "^0.4.2",
+ "@humanwhocodes/config-array": "^0.5.0",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.0.1",
+ "doctrine": "^3.0.0",
+ "enquirer": "^2.3.5",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^2.1.0",
+ "eslint-visitor-keys": "^2.0.0",
+ "espree": "^7.3.1",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^5.1.2",
+ "globals": "^13.6.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^3.13.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.0.4",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "progress": "^2.0.0",
+ "regexpp": "^3.1.0",
+ "semver": "^7.2.1",
+ "strip-ansi": "^6.0.0",
+ "strip-json-comments": "^3.1.0",
+ "table": "^6.0.9",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
+ "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
+ }
+ },
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ }
+ }
+ },
+ "eslint-config-strongloop": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-strongloop/-/eslint-config-strongloop-2.1.0.tgz",
+ "integrity": "sha1-dj3Rmt/OiNewBR5uJV8a43eDtMY=",
+ "dev": true
+ },
+ "eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "eslint-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+ "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^2.0.0"
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true
+ },
+ "espree": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+ "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.4.0",
+ "acorn-jsx": "^5.3.1",
+ "eslint-visitor-keys": "^1.3.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+ "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+ "dev": true
+ }
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+ "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+ "dev": true
+ }
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
"eta": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.1.tgz",
- "integrity": "sha512-H8npoci2J/7XiPnVcCVulBSPsTNGvGaINyMjQDU8AFqp9LGsEYS88g2CiU+d01Sg44WtX7o4nb8wUJ9vnI+tiA=="
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.2.tgz",
+ "integrity": "sha512-Z05sK2DRWAfBhG/2cwAOWuMoQIYaVYJCQrz2g2O/ekUjzWHNBv9L1pnblVDoDkKSb/AZ5tWZ0N/v4iaIU4+HjA=="
},
"etag": {
"version": "1.8.1",
@@ -499,16 +1176,74 @@
}
}
},
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz",
+ "integrity": "sha512-GnLuqj/pvQ7pX8/L4J84nijv6sAnlwvSDpMkJi9i7nPmPxGtRPkBSStfvDW5l6nMdX9VWe+pkKWFTgD+vF2QSQ==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
"fast-safe-stringify": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
"integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
},
+ "fastq": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz",
+ "integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
"fecha": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz",
"integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q=="
},
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
"finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
@@ -523,6 +1258,22 @@
"unpipe": "~1.0.0"
}
},
+ "flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.0.tgz",
+ "integrity": "sha512-XprP7lDrVT+kE2c2YlfiV+IfS9zxukiIOvNamPNsImNhXadSsQEbosItdL9bUQlCZXR13SvPk20BjWSWLA7m4A==",
+ "dev": true
+ },
"fn.name": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
@@ -551,6 +1302,12 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+ "dev": true
+ },
"gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
@@ -579,6 +1336,49 @@
"path-is-absolute": "^1.0.0"
}
},
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globals": {
+ "version": "13.9.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz",
+ "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "globby": {
+ "version": "11.0.4",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz",
+ "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.1.1",
+ "ignore": "^5.1.4",
+ "merge2": "^1.3.0",
+ "slash": "^3.0.0"
+ }
+ },
+ "greeting-time": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/greeting-time/-/greeting-time-1.0.0.tgz",
+ "integrity": "sha512-SjefO4MuSaL1xvFtxMZKnoROsh/t8s3UaWjNfsRA7IvD2o7picqySgYk7NAZmhEaCieQhXsrbjfP33aGRADxbg=="
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@@ -638,6 +1438,28 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
+ "ignore": {
+ "version": "5.1.8",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -662,6 +1484,12 @@
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
},
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
@@ -670,6 +1498,21 @@
"number-is-nan": "^1.0.0"
}
},
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
"is-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
@@ -680,11 +1523,73 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "dev": true
+ },
"kuler": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
},
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
+ "dev": true
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "lodash.truncate": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+ "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=",
+ "dev": true
+ },
"logform": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz",
@@ -737,11 +1642,27 @@
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
+ "micromatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+ "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.1",
+ "picomatch": "^2.2.3"
+ }
+ },
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
@@ -860,6 +1781,12 @@
}
}
},
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
@@ -876,9 +1803,9 @@
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
"nodemailer": {
- "version": "6.6.1",
- "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.1.tgz",
- "integrity": "sha512-1xzFN3gqv+/qJ6YRyxBxfTYstLNt0FCtZaFRvf4Sg9wxNGWbwFmGXVpfSi6ThGK6aRxAo+KjHtYSW8NvCsNSAg=="
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.2.tgz",
+ "integrity": "sha512-YSzu7TLbI+bsjCis/TZlAXBoM4y93HhlIgo0P5oiA2ua9Z4k+E2Fod//ybIzdJxOlXGRcHIh/WaeCBehvxZb/Q=="
},
"nopt": {
"version": "5.0.0",
@@ -938,6 +1865,29 @@
"fn.name": "1.x.x"
}
},
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ }
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -948,16 +1898,46 @@
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
+ "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
+ "progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true
+ },
"proxy-addr": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
@@ -967,11 +1947,23 @@
"ipaddr.js": "1.9.1"
}
},
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
"qs": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
},
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
"random-bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
@@ -1003,6 +1995,30 @@
"util-deprecate": "^1.0.1"
}
},
+ "regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true
+ },
+ "require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -1011,6 +2027,15 @@
"glob": "^7.1.3"
}
},
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -1077,6 +2102,21 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
"signal-exit": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
@@ -1090,6 +2130,61 @@
"is-arrayish": "^0.3.1"
}
},
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ }
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
"sqlstring": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
@@ -1143,6 +2238,87 @@
"ansi-regex": "^2.0.0"
}
},
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "table": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz",
+ "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==",
+ "dev": true,
+ "requires": {
+ "ajv": "^8.0.1",
+ "lodash.clonedeep": "^4.5.0",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "8.6.1",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz",
+ "integrity": "sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
+ "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ }
+ }
+ },
"tar": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
@@ -1161,6 +2337,21 @@
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
},
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
@@ -1171,6 +2362,36 @@
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
"integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
},
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true
+ },
"type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
@@ -1185,6 +2406,12 @@
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
+ "typescript": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
+ "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
+ "dev": true
+ },
"uid-safe": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
@@ -1198,6 +2425,15 @@
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -1208,11 +2444,26 @@
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
+ "v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
"wide-align": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
@@ -1270,6 +2521,12 @@
}
}
},
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
diff --git a/package.json b/package.json
index 23f369b..eb8fcdf 100644
--- a/package.json
+++ b/package.json
@@ -4,8 +4,13 @@
"description": "The elevatormap rewritten",
"main": "index.js",
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 0",
- "start": "node index.js"
+ "makeJS": "tsc index.ts",
+ "lint": "eslint . --ext .ts",
+ "makeJSwatch": "tsc -w index.ts",
+ "start": "tsc index.ts && node index.js",
+ "preChecks": "npm outdated && npm audit",
+ "startBeforeMerge": "eslint . --ext .ts && tsc index.ts && node index.js",
+ "nodemon": "nodemon index.js"
},
"repository": {
"type": "git",
@@ -20,14 +25,23 @@
"dependencies": {
"bcrypt": "^5.0.1",
"body-parser": "^1.19.0",
- "eta": "^1.12.1",
+ "eta": "^1.12.2",
"express": "^4.17.1",
"express-session": "^1.17.2",
+ "greeting-time": "^1.0.0",
"hcaptcha": "0.0.2",
"helmet": "^4.6.0",
"multer": "^1.4.2",
"mysql": "^2.18.1",
- "nodemailer": "^6.6.1",
+ "nodemailer": "^6.6.2",
"winston": "^3.3.3"
+ },
+ "devDependencies": {
+ "@types/node": "^16.0.0",
+ "@typescript-eslint/eslint-plugin": "^4.21.0",
+ "@typescript-eslint/parser": "^4.21.0",
+ "eslint": "^7.26.0",
+ "eslint-config-strongloop": "^2.1.0",
+ "typescript": "^4.2.4"
}
}
diff --git a/routes/api.route.ts b/routes/api.route.ts
new file mode 100644
index 0000000..dd6f74d
--- /dev/null
+++ b/routes/api.route.ts
@@ -0,0 +1,312 @@
+module.exports = function (app, con, mysqlIsUpAndOkay, logger) {
+ const multer = require("multer");
+ const upload = multer({ dest: "static/uploads/" });
+ const fs = require("fs");
+ const path = require("path");
+
+ app.get("/api/getElevatorById", function (req, res) {
+ console.log(req.query);
+ if (req.query.id != undefined) {
+ // All parameters are there
+ res.setHeader("Content-Type", "application/json");
+ try {
+ const id = parseFloat(req.query.id);
+ } catch (error) {
+ res.send(
+ JSON.stringify({ state: "Failed", message: "Invalid arguments" })
+ );
+ res.status(400);
+ return;
+ }
+ const id = parseFloat(req.query.id);
+
+ con.query(
+ "SELECT * FROM elevators WHERE id=" + id,
+ function (err, result) {
+ if (err) {
+ res.status(500);
+ res.send(
+ JSON.stringify({
+ state: "Failed",
+ message: "A server side error occured.",
+ results: [],
+ })
+ );
+ logger.error("The server failed to execute a request");
+ console.log(err);
+ mysqlIsUpAndOkay = false;
+ } else {
+ console.log(result[0]);
+ res.status(200);
+ res.send(
+ JSON.stringify({
+ state: "Ok",
+ message: "Successful.",
+ results: result,
+ })
+ );
+ }
+ }
+ );
+ } else {
+ // Welp something is missing
+ res.status(400);
+ res.setHeader("Content-Type", "application/json");
+ res.send(JSON.stringify({ state: "Failed", message: "Missing arguments" }));
+ }
+ });
+
+ app.get("/api/resolveNameById", function (req, res) {
+ if (req.query.id != undefined && req.query.id != "") {
+
+ const sql = "SELECT username FROM users WHERE id=?";
+ con.query(sql, [req.query.id], function (err, result) {
+ if (err) {
+ res.status(500);
+ res.send(
+ JSON.stringify({
+ state: "Failed",
+ message: "A server side error occured.",
+ results: [],
+ })
+ );
+ logger.error("The server failed to execute a request");
+ mysqlIsUpAndOkay = false;
+ } else {
+ console.log(result[0]);
+ res.status(200);
+ res.setHeader("Content-Type", "application/json");
+ res.send(
+ JSON.stringify({ state: "Ok", message: "", results: result })
+ );
+ }
+ }
+ );
+ } else {
+ res.status(400);
+ res.setHeader("Content-Type", "application/json");
+ res.send(JSON.stringify({ state: "Failed", message: "Missing argument: id" }));
+ }
+ });
+
+
+ app.get("/api/getElevatorLocation", function (req, res) {
+ if (
+ req.query.lan != undefined &&
+ req.query.lat != undefined &&
+ req.query.radius != undefined
+ ) {
+ // All parameters are there
+ res.setHeader("Content-Type", "application/json");
+ try {
+ const lan = parseFloat(req.query.lan);
+ const lat = parseFloat(req.query.lat);
+ const radius = parseFloat(req.query.radius);
+ } catch (error) {
+ res.send(
+ JSON.stringify({ state: "Failed", message: "Invalid arguments" })
+ );
+ res.status(400);
+ return;
+ }
+ const lan = parseFloat(req.query.lan);
+ const lat = parseFloat(req.query.lat);
+ const radius = parseFloat(req.query.radius);
+
+ // TODO: Return just the elevators in the viewers area
+
+ con.query(
+ "SELECT id, lat, lng FROM elevators",
+ function (err, result, fields) {
+ if (err) {
+ res.status(500);
+ res.send(
+ JSON.stringify({
+ state: "Failed",
+ message: "A server side error occured.",
+ results: [],
+ })
+ );
+ logger.error("The server failed to execute a request");
+ mysqlIsUpAndOkay = false;
+ } else {
+ console.log(result[0]);
+ res.status(200);
+ res.send(
+ JSON.stringify({ state: "Ok", message: "", results: result })
+ );
+ }
+ }
+ );
+ } else {
+ // Welp something is missing
+ res.status(400);
+ res.setHeader("Content-Type", "application/json");
+ res.send(JSON.stringify({ state: "Failed", message: "Missing arguments" }));
+ }
+ });
+
+ // returns an object with the cookies' name as keys
+ const getAppCookies = (req) => {
+ // We extract the raw cookies from the request headers
+ const rawCookies = req.headers.cookie.split("; ");
+ // rawCookies = ['myapp=secretcookie, 'analytics_cookie=beacon;']
+
+ const parsedCookies = {};
+ rawCookies.forEach((rawCookie) => {
+ const parsedCookie = rawCookie.split("=");
+ // parsedCookie = ['myapp', 'secretcookie'], ['analytics_cookie', 'beacon']
+ parsedCookies[parsedCookie[0]] = parsedCookie[1];
+ });
+ return parsedCookies;
+ };
+
+ app.post("/api/saveNewElevatorMeta", function (req, res) {
+ const sess = req.session;
+ const tempJs = JSON.parse(decodeURIComponent(getAppCookies(req)["tempStore"]));
+ const sql =
+ "INSERT INTO elevators (lat, lng, manufacturer, modell, info, visitabilty, technology, amountOfFloors, maxPassangers, maxWeight, images, creator) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '{ \"images\": []}', ?)";
+ con.query(
+ sql,
+ [
+ tempJs.lat,
+ tempJs.lng,
+ tempJs.manuf,
+ tempJs.model,
+ tempJs.description,
+ tempJs.visit,
+ tempJs.type,
+ tempJs.flor,
+ tempJs.pepl,
+ tempJs.weig,
+ sess.uid
+ ],
+ function (err, result) {
+ if (err) throw err;
+ console.log("1 record inserted with id " + result.insertId);
+ res.setHeader("Content-Type", "application/json");
+
+ res.send(
+ JSON.stringify({ state: "Okay", message: "Ok. No fault!", id: result.insertId })
+ );
+ res.status(200);
+ }
+ );
+ });
+
+
+ app.post("/api/uploadImage", upload.any(), function (req, res) {
+ console.log(req.query.id)
+ let i = 0;
+ const sql = 'SELECT id, images FROM elevators WHERE id=?';
+ const allImages = []
+ while (i < req.files.length) {
+ const fObj = req.files[i];
+ const currentPath = path.join(fObj["path"]);
+ const destinationPath =
+ currentPath +
+ "." +
+ fObj["originalname"].split(".")[
+ fObj["originalname"].split(".").length - 1
+ ]; // Add the file end
+
+ fs.rename(currentPath, destinationPath, function (err) {
+ if (err) {
+ throw err;
+ } else {
+ console.log("Successfully moved the file!");
+ }
+ });
+ allImages.push({ "path": destinationPath, "alt": "No alt was provided." })
+ i++;
+ }
+
+ con.query(
+ sql, [req.query.id],
+ function (err, result, fields) {
+ if (err) {
+ res.status(500);
+ res.send(
+ JSON.stringify({
+ state: "Failed",
+ message: "A server side error occured.",
+ results: [],
+ })
+ );
+ logger.error("The server failed to execute a request");
+ mysqlIsUpAndOkay = false;
+ } else {
+ const jData = JSON.parse(result[0].images)
+ console.log(jData)
+ jData.images.push.spread(jData.images, allImages)
+ console.log(jData);
+ console.log(result);
+ const sql = "UPDATE elevators SET images = ? WHERE id = ?";
+ con.query(sql, [JSON.stringify(jData), req.query.id], function (err) {
+ if (err) {
+ console.log("Update failure")
+ } else {
+ console.log("Okay")
+ }
+
+ })
+ }
+ }
+ );
+
+ // Save Image End
+ });
+
+
+ app.get("/api/getElevators", function (req, res) {
+ console.log(req.query);
+ if (
+ req.query.lan != undefined &&
+ req.query.lat != undefined &&
+ req.query.radius != undefined
+ ) {
+ // All parameters are there
+ res.setHeader("Content-Type", "application/json");
+ try {
+ const lan = parseFloat(req.query.lan);
+ const lat = parseFloat(req.query.lat);
+ const radius = parseFloat(req.query.radius);
+ } catch (error) {
+ res.send(
+ JSON.stringify({ state: "Failed", message: "Invalid arguments" })
+ );
+ res.status(400);
+ return;
+ }
+ const lan = parseFloat(req.query.lan);
+ const lat = parseFloat(req.query.lat);
+ const radius = parseFloat(req.query.radius);
+
+ // TODO: Return just the elevators in the viewers area
+
+ con.query("SELECT * FROM elevators", function (err, result) {
+ if (err) {
+ res.status(500);
+ res.send(
+ JSON.stringify({
+ state: "Failed",
+ message: "A server side error occured.",
+ results: [],
+ })
+ );
+ logger.error("The server failed to execute a request");
+ mysqlIsUpAndOkay = false;
+ } else {
+ console.log(result[0]);
+ res.status(200);
+ res.send(JSON.stringify({ state: "Ok", message: "", results: result }));
+ }
+ });
+ } else {
+ // Welp something is missing
+ res.status(400);
+ res.setHeader("Content-Type", "application/json");
+ res.send(JSON.stringify({ state: "Failed", message: "Missing arguments" }));
+ }
+ });
+}
\ No newline at end of file
diff --git a/routes/auth.route.ts b/routes/auth.route.ts
new file mode 100644
index 0000000..8d55b2e
--- /dev/null
+++ b/routes/auth.route.ts
@@ -0,0 +1,443 @@
+module.exports = function (app, con, logger, metainfo, jsonConfig) {
+ const greetingTime = require("greeting-time");
+ const fs = require("fs");
+ const Eta = require("eta");
+ const { verify } = require("hcaptcha");
+ const bcrypt = require("bcrypt");
+ const cryptoF = require("crypto");
+ const saltRounds = 10;
+
+ const mailRegex =
+ /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
+
+ app.get("/logout", function (req, res) {
+ req.session.destroy();
+ const data = fs.readFileSync("templates/redirect.html", "utf8");
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Logout",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ url: "/",
+ })
+ );
+ });
+ app.get("/verify*", function (req, res) {
+ console.log(req.url.split("/")[2]);
+ const stmt = "SELECT * FROM mailverification WHERE token = ?;";
+
+ con.query(stmt, [req.url.split("/")[2]], function (err, result) {
+ if (err) {
+ res.status(404);
+ res.send(
+ JSON.stringify({ state: "Failed", message: "Database error occured" })
+ );
+ logger.error(err);
+ } else {
+ if (result.length == 0) {
+ res.status(404);
+ res.send(
+ JSON.stringify({ state: "Failed", message: "Link already done" })
+ );
+ } else {
+ console.log(result);
+ res.status(200);
+ const stmt2 = "DELETE FROM mailverification WHERE id=?";
+ console.log(result[0].id);
+ con.query(stmt2, [result[0].id], function (err, result, fields) {
+ // TODO handling of this
+ //logger.debug(err)
+ //console.log(result)
+ });
+ const stmt3 = "UPDATE users SET verificationState=1 WHERE email=?";
+ con.query(
+ stmt3,
+ [result[0].targetMail],
+ function (err, result, fields) {
+ // TODO handling of this
+ //logger.debug(err)
+ //console.log(result)
+ }
+ );
+ res.send(JSON.stringify({ state: "OK", message: "Done!" }));
+ }
+ }
+ });
+ });
+
+
+
+ app.post("/register", function (req, res) {
+ const sess = req.session;
+ let resu;
+ verify(jsonConfig.hCaptcha.secret, req.body["g-recaptcha-response"]).then(
+ (data) => (resu = data)
+ );
+ /*.catch(setTimeout(() => {
+ //if(resu.success == false){
+ console.log("HERE");
+ const data = fs.readFileSync("templates/genericError.html", "utf8");
+ resu = "-1";
+ con
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Error",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ displayText: "There was an issue with the Captcha",
+ })
+ );
+ //}
+
+ }, 0)
+ );*/
+
+ if (req.body.pass == req.body.pass2) {
+
+ if (mailRegex.test(req.body.email)) {
+ setTimeout(() => {
+ console.log(resu);
+ if (resu.success == true) {
+ bcrypt.hash(req.body.pass, saltRounds, (err, hash) => {
+ const data = fs.readFileSync(
+ "templates/genericError.html",
+ "utf8"
+ );
+ // SQL INSERT
+
+ const stmt =
+ "INSERT INTO users(email, username, passwordHash) VALUES(?, ?, ?)";
+ const stmt2 =
+ "INSERT INTO mailverification(targetMail, userID, token) VALUES(?, ?, ?)";
+ cryptoF.randomBytes(48, function (err, buffer) {
+ const token = buffer.toString("hex");
+ con.query(
+ stmt,
+ [req.body.email, req.body.username, hash],
+ (err, results1) => {
+ if (err) {
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Error",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ displayText:
+ "An error occured while creating your account.",
+ })
+ );
+ return console.error(err.message);
+ } else {
+ // Create mail verification
+ con.query(
+ stmt2,
+ [req.body.email, results1.insertId, token],
+ (err, results) => {
+ if (err) {
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Error",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ displayText:
+ "An error occured while creating your account.",
+ })
+ );
+ return console.error(err.message);
+ } else {
+ sess.username = req.body.username;
+ sess.uid = String(results1.insertId);
+ sess.mail = req.body.email;
+ // get inserted id
+ logger.info("Inserted Id:" + results.insertId);
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Error",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ displayText: "OK " + hash,
+ })
+ );
+ sendVerificationMail(results.insertId);
+ }
+ }
+ );
+ }
+ }
+ );
+ });
+ });
+ } else {
+ const data = fs.readFileSync("templates/register.html", "utf8");
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Register",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ sitekey: jsonConfig.hCaptcha.sitekey,
+ error: true,
+ errorMessage: "You failed the captcha, please try again.",
+ })
+ );
+ }
+ }, 200);
+ } else {
+ // Passwords don't match up
+ const data = fs.readFileSync("templates/register.html", "utf8");
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Register",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ sitekey: jsonConfig.hCaptcha.sitekey,
+ error: true,
+ errorMessage: "The E-Mail given is not valid",
+ })
+ );
+ }
+ } else {
+ // Passwords don't match up
+ const data = fs.readFileSync("templates/register.html", "utf8");
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Register",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ sitekey: jsonConfig.hCaptcha.sitekey,
+ error: true,
+ errorMessage: "The password have to match up.",
+ })
+ );
+ }
+ });
+
+
+ app.get("/register", function (req, res) {
+ const data = fs.readFileSync("templates/register.html", "utf8");
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Register",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ sitekey: jsonConfig.hCaptcha.sitekey,
+ })
+ );
+
+ });
+
+
+
+ app.get("/profile", function (req, res) {
+ if (req.session.username != undefined) {
+ let greeting = greetingTime(new Date());
+ greeting += req.session.username;
+ const hash = cryptoF
+ .createHash("md5")
+ .update(req.session.mail.replace(" ", "").toLowerCase())
+ .digest("hex");
+ const gravatarURL = "https://www.gravatar.com/avatar/" + hash;
+ const data = fs.readFileSync("templates/profile.html", "utf8");
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Profile",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ greeting: greeting,
+ gravatarURL: gravatarURL,
+ })
+ );
+ } else {
+ const data = fs.readFileSync("templates/redirect.html", "utf8");
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Profile",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ url: "/login",
+ })
+ );
+ }
+
+ });
+
+ app.get("/login", function (req, res) {
+
+ const data = fs.readFileSync("templates/login.html", "utf8");
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Login",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ })
+ );
+
+ });
+
+
+ app.post("/login", function (req, res) {
+ const password = req.body.pass;
+ const mail = req.body.email;
+ const sess = req.session;
+ console.log(req.body.pass);
+
+ // Check if okay
+ if (
+ mail != undefined &&
+ mail != "" &&
+ password != undefined &&
+ password != ""
+ ) {
+ if (mailRegex.test(mail)) {
+ const stmt = "SELECT * FROM users WHERE email='?';";
+ con.query(stmt, [mail], function (err, result) {
+ if (err) throw err; // TODO proper error page
+ if (result.length == 0) {
+ const data = fs.readFileSync("templates/login.html", "utf8");
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Ok",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ error: true,
+ errorMessage: "This user does not exist!",
+ })
+ );
+ } else {
+ bcrypt.compare(
+ password,
+ result[0].passwordHash,
+ function (error, response) {
+ if (response) {
+ // Login okay
+ sess.username = result[0].username;
+ sess.uid = String(result[0].id);
+ sess.mail = result[0].email;
+
+ const data = fs.readFileSync("templates/redirect.html", "utf8");
+ if (req.query.r != undefined && req.query.r != "") {
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Ok",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ url: req.query.r,
+ })
+ );
+
+ } else {
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Ok",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ url: "/profile",
+ })
+ );
+ }
+
+ } else {
+ // Password falsch
+ const data = fs.readFileSync("templates/login.html", "utf8");
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Ok",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ error: true,
+ errorMessage: "The given password is wrong.",
+ })
+ );
+ }
+ }
+ );
+ }
+ });
+ } else {
+ const data = fs.readFileSync("templates/login.html", "utf8");
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Ok",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ error: true,
+ errorMessage: "The given E-Mail is invalid.",
+ })
+ );
+ }
+ } else {
+ logger.warn(
+ "The login form did not sent all data. Dump: \n Password: " +
+ password +
+ " \n E-Mail: " +
+ mail
+ );
+ const data = fs.readFileSync("templates/genericError.html", "utf8");
+ const displayText = "The form did not sent all the information needed.";
+ res.send(
+ Eta.render(data, {
+ author: metainfo.author,
+ desc: metainfo.desc,
+ siteTitel: metainfo.sitePrefix + "Error",
+ fontawesomeKey: jsonConfig.fontAwesome,
+ displayText: displayText,
+ })
+ );
+ }
+ });
+
+ // sendVerificationMail(2);
+ function sendVerificationMail(userId) {
+ // Query for the mail
+ const stmt = "SELECT * FROM mailverification WHERE id=?";// + userId;
+ con.query(stmt, [userId], function (err, result, fields) {
+ if (err) throw err; // TODO proper error handling
+ if (result.length == 0) {
+ logger.warn(
+ "sendVerificationMail failed because ID " + userId + " doesnt exist!"
+ );
+ } else {
+ const emailContent =
+ "Hi! \n You have created an account for the open elevator map. To finalize the process please verify your E-Mail adress. Use this link: http://" +
+ serverAdress +
+ "/verify/" +
+ result[0].token;
+ transport.sendMail({
+ from: '"Elevator map " <' + mailConf.username + ">", // sender address
+ to: result[0].targetMail, // list of receivers
+ subject: "[Elevator map] Please verify your Mailadress", // Subject line
+ text: emailContent, // plain text body
+ html: emailContent.replace("\n", "
"), // html body
+ });
+ }
+
+ console.log(result);
+ });
+
+ /*
+ let info = await transporter.sendMail({
+ from: '"Elevator map " <' + mysqlData.username + '>', // sender address
+ to: "bar@example.com, baz@example.com", // list of receivers
+ subject: "Hello ✔", // Subject line
+ text: "Hello world?", // plain text body
+ html: "Hello world?", // html body
+ });*/
+ }
+
+
+}
\ No newline at end of file
diff --git a/routes/debug.route.ts b/routes/debug.route.ts
new file mode 100644
index 0000000..1a5e27c
--- /dev/null
+++ b/routes/debug.route.ts
@@ -0,0 +1,6 @@
+module.exports = function (app) {
+ app.get("/debug/showSessionInfo", function (req, res) {
+ res.send(JSON.stringify(req.session));
+ });
+
+}
\ No newline at end of file