Removed functions from server.js and put them in their own controllers. Updated .gitignore to ignore dbs/configs/.idea files
parent
a5fbb94162
commit
ca745ca470
|
@ -6,3 +6,6 @@ package-lock.json
|
||||||
database.sqlite
|
database.sqlite
|
||||||
config.js
|
config.js
|
||||||
.vscode
|
.vscode
|
||||||
|
.idea
|
||||||
|
database.sqlite
|
||||||
|
config.js
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
|
let models;
|
||||||
|
let logger;
|
||||||
|
|
||||||
|
|
||||||
async function validateJWT(token, key) {
|
async function validateJWT(token, key) {
|
||||||
|
@ -14,6 +15,31 @@ async function validateJWT(token, key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
async function getAuthenticatedAccount(req, res) {
|
||||||
validateJWT: validateJWT
|
const sessionCookie = (req.signedCookies !== undefined ? req.signedCookies.session : null);
|
||||||
|
if (!sessionCookie || sessionCookie.expires <= Date.now()) { return null; }
|
||||||
|
const email = sessionCookie.account.trim().toLowerCase();
|
||||||
|
|
||||||
|
|
||||||
|
// don't need to wait for this, logging a ping if a banned user attempts to sign in
|
||||||
|
|
||||||
|
// TODO stop storing emails in the cookie
|
||||||
|
const account = await models.users.getAccountFromEmail(email)
|
||||||
|
|
||||||
|
if (!account || account.banned) {
|
||||||
|
res ? res.clearCookie('session') : logger.warn(`getAuthenticatedAccount unable to clear banned user (${account.email}) cookie, res not passed`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = (_models, _logger) => {
|
||||||
|
models = _models;
|
||||||
|
logger = _logger;
|
||||||
|
|
||||||
|
return {
|
||||||
|
validateJWT: validateJWT,
|
||||||
|
getAuthenticatedAccount: getAuthenticatedAccount
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
let models;
|
||||||
|
let logger;
|
||||||
|
|
||||||
|
|
||||||
|
function formatDuration(durationSeconds) {
|
||||||
|
durationSeconds = Math.round(durationSeconds);
|
||||||
|
const secs = durationSeconds % 60;
|
||||||
|
let mins = Math.floor(durationSeconds / 60);
|
||||||
|
const hours = Math.floor(mins / 60);
|
||||||
|
mins = mins % 60;
|
||||||
|
|
||||||
|
let response = '';
|
||||||
|
if (hours > 0) response += hours + 'h ';
|
||||||
|
if (hours > 0 || mins > 0) response += mins + 'm ';
|
||||||
|
response += secs + 's';
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function simpleStringify(object) {
|
||||||
|
let simpleObject = {};
|
||||||
|
for (var prop in object) {
|
||||||
|
if (!object.hasOwnProperty(prop)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (typeof (object[prop]) == 'object') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (typeof (object[prop]) == 'function') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
simpleObject[prop] = object[prop];
|
||||||
|
}
|
||||||
|
return JSON.stringify(simpleObject); // returns cleaned up JSON
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function formatDate(timestampMs) {
|
||||||
|
return new Date(timestampMs).toISOString().replace(/T/, ' ').replace(/\..+/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = (_models, _logger) => {
|
||||||
|
models = _models;
|
||||||
|
logger = _logger;
|
||||||
|
|
||||||
|
return {
|
||||||
|
formatDuration, simpleStringify, formatDate
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,13 @@
|
||||||
|
const config = require('./../config');
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = async (models, logger) => {
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
authenticationController: require('./authentication')
|
return {
|
||||||
}
|
authentication: require('./authentication')(models, logger),
|
||||||
|
helpers: require('./helpers')(models, logger),
|
||||||
|
storage: require('./storage')(models, logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
const config = require('./../config');
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
|
let models;
|
||||||
|
let logger;
|
||||||
|
|
||||||
|
let totalStorageUsed;
|
||||||
|
|
||||||
|
function initializeStorage() {
|
||||||
|
var verifiedPath = mkDirByPathSync(config.storagePath, {isRelativeToScript: (config.storagePath.indexOf("/") === 0 ? false : true)});
|
||||||
|
if (verifiedPath != null)
|
||||||
|
logger.info("Verified storage path " + verifiedPath);
|
||||||
|
else {
|
||||||
|
logger.error("Unable to verify storage path '" + config.storagePath + "', check filesystem / permissions");
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mkDirByPathSync(targetDir, {isRelativeToScript = false} = {}) {
|
||||||
|
const sep = path.sep;
|
||||||
|
const initDir = path.isAbsolute(targetDir) ? sep : '';
|
||||||
|
|
||||||
|
// TODO does this break anything? Commented out code will create a folder in the /controllers directory, defined __basedir as a global var in server.js
|
||||||
|
const baseDir = __basedir; //isRelativeToScript ? __dirname : '.';
|
||||||
|
|
||||||
|
return targetDir.split(sep).reduce((parentDir, childDir) => {
|
||||||
|
const curDir = path.resolve(baseDir, parentDir, childDir);
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(curDir);
|
||||||
|
} catch (err) {
|
||||||
|
console.debug(err);
|
||||||
|
if (err.code === 'EEXIST') { // curDir already exists!
|
||||||
|
return curDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
|
||||||
|
if (err.code === 'ENOENT') { // Throw the original parentDir error on curDir `ENOENT` failure.
|
||||||
|
logger.error(`EACCES: permission denied, mkdir '${parentDir}'`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const caughtErr = ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1;
|
||||||
|
if (!caughtErr || (caughtErr && curDir === path.resolve(targetDir))) {
|
||||||
|
logger.error("'EACCES', 'EPERM', 'EISDIR' during mkdir");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return curDir;
|
||||||
|
}, initDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function writeFileSync(path, buffer, permission) {
|
||||||
|
let fileDescriptor;
|
||||||
|
try {
|
||||||
|
fileDescriptor = fs.openSync(path, 'w', permission);
|
||||||
|
} catch (e) {
|
||||||
|
fs.chmodSync(path, permission);
|
||||||
|
fileDescriptor = fs.openSync(path, 'w', permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileDescriptor) {
|
||||||
|
fs.writeSync(fileDescriptor, buffer, 0, buffer.length, 0);
|
||||||
|
fs.closeSync(fileDescriptor);
|
||||||
|
logger.info("writeFileSync wiriting to '" + path + "' successful");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
logger.error("writeFileSync writing to '" + path + "' failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveUploadedFile(buffer, directory, filename) {
|
||||||
|
logger.info(`moveUploadedFile called with ${filename} -> ${directory}'`);
|
||||||
|
|
||||||
|
if (directory.indexOf("..") >= 0 || filename.indexOf("..") >= 0) {
|
||||||
|
logger.error("moveUploadedFile failed, .. in directory or filename");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.storagePath.lastIndexOf("/") !== config.storagePath.length - 1)
|
||||||
|
directory = '/' + directory;
|
||||||
|
if (directory.lastIndexOf("/") !== directory.length - 1)
|
||||||
|
directory = directory + '/';
|
||||||
|
|
||||||
|
const finalPath = mkDirByPathSync(config.storagePath + directory, {isRelativeToScript: (config.storagePath.indexOf("/") === 0 ? false : true)});
|
||||||
|
if (finalPath && finalPath.length > 0) {
|
||||||
|
if (writeFileSync(finalPath + "/" + filename, buffer, 0o660)) {
|
||||||
|
logger.info("moveUploadedFile successfully written '" + (finalPath + "/" + filename) + "'");
|
||||||
|
return finalPath + "/" + filename;
|
||||||
|
}
|
||||||
|
logger.error("moveUploadedFile failed to writeFileSync");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
logger.error("moveUploadedFile invalid final path, check permissions to create / write '" + (config.storagePath + directory) + "'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function updateTotalStorageUsed() {
|
||||||
|
const verifiedPath = mkDirByPathSync(config.storagePath, {isRelativeToScript: (config.storagePath.indexOf("/") === 0 ? false : true)});
|
||||||
|
if (verifiedPath !== null) {
|
||||||
|
try {
|
||||||
|
totalStorageUsed = execSync("du -hs " + verifiedPath + " | awk -F'\t' '{print $1;}'").toString();
|
||||||
|
} catch (exception) {
|
||||||
|
totalStorageUsed = "Unsupported Platform";
|
||||||
|
logger.debug(`Unable to calculate storage used, only supported on systems with 'du' available`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(function () {
|
||||||
|
updateTotalStorageUsed();
|
||||||
|
}, 120000); // update the used storage each 120 seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getTotalStorageUsed() {
|
||||||
|
return totalStorageUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = (_models, _logger) => {
|
||||||
|
models = _models;
|
||||||
|
logger = _logger;
|
||||||
|
|
||||||
|
return {
|
||||||
|
initializeStorage, mkDirByPathSync, writeFileSync, moveUploadedFile, updateTotalStorageUsed, getTotalStorageUsed
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,7 @@ const sqlite3 = require('sqlite3')
|
||||||
const {open} = require('sqlite')
|
const {open} = require('sqlite')
|
||||||
const config = require('./../config');
|
const config = require('./../config');
|
||||||
|
|
||||||
|
async function validateDatabase(db, logger) {
|
||||||
|
|
||||||
|
|
||||||
module.exports = async (logger) => {
|
|
||||||
let db;
|
|
||||||
try {
|
try {
|
||||||
db = await open({
|
db = await open({
|
||||||
filename: config.databaseFile,
|
filename: config.databaseFile,
|
||||||
|
@ -22,12 +18,36 @@ module.exports = async (logger) => {
|
||||||
logger.error(exception);
|
logger.error(exception);
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = async (logger) => {
|
||||||
|
let db;
|
||||||
|
|
||||||
|
try {
|
||||||
|
db = await open({
|
||||||
|
filename: config.databaseFile,
|
||||||
|
driver: sqlite3.Database,
|
||||||
|
mode: sqlite3.OPEN_READWRITE
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (exception) {
|
||||||
|
logger.error(exception);
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// I'm not sure we _really_ need to wait for this, since it'll exit the application if it's invalid anyway.
|
||||||
|
|
||||||
|
await validateDatabase(db, logger);
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
db,
|
db,
|
||||||
models: {
|
models: {
|
||||||
drivesModel: require('./drives')(db)
|
drivesModel: require('./drives')(db),
|
||||||
|
users: require('./users')(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
let db;
|
||||||
|
|
||||||
|
async function userPing(email) {
|
||||||
|
return await db.run('UPDATE accounts SET last_ping = ? WHERE email = ?', Date.now(), email);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAccountFromEmail(email) {
|
||||||
|
return await db.get('SELECT * FROM accounts WHERE LOWER(email) = ?', email);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = (_db) => {
|
||||||
|
db = _db;
|
||||||
|
|
||||||
|
return {
|
||||||
|
userPing,
|
||||||
|
getAccountFromEmail
|
||||||
|
}
|
||||||
|
}
|
252
server.js
252
server.js
|
@ -3,202 +3,35 @@ const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const log4js = require('log4js');
|
const log4js = require('log4js');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const lockfile = require('proper-lockfile');
|
const lockfile = require('proper-lockfile');
|
||||||
|
const http = require('http');
|
||||||
var http = require('http');
|
const https = require('https');
|
||||||
var https = require('https');
|
|
||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const cors = require('cors');
|
const cors = require('cors');
|
||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
const cookieParser = require('cookie-parser');
|
const cookieParser = require('cookie-parser');
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
|
|
||||||
const sendmail = require('sendmail')();
|
const sendmail = require('sendmail')();
|
||||||
|
|
||||||
const htmlspecialchars = require('htmlspecialchars');
|
const htmlspecialchars = require('htmlspecialchars');
|
||||||
|
|
||||||
const dirTree = require("directory-tree");
|
const dirTree = require("directory-tree");
|
||||||
const execSync = require('child_process').execSync;
|
const execSync = require('child_process').execSync;
|
||||||
|
|
||||||
|
|
||||||
log4js.configure({
|
log4js.configure({
|
||||||
appenders: {logfile: {type: "file", filename: "server.log"}, out: {type: "console"}},
|
appenders: {logfile: {type: "file", filename: "server.log"}, out: {type: "console"}},
|
||||||
categories: {default: {appenders: ['out', 'logfile'], level: 'info'}}
|
categories: {default: {appenders: ['out', 'logfile'], level: 'info'}}
|
||||||
});
|
});
|
||||||
|
|
||||||
var logger = log4js.getLogger('default');
|
const logger = log4js.getLogger('default');
|
||||||
|
|
||||||
|
// TODO evaluate if this is the best way to determine the root of project
|
||||||
|
global.__basedir = __dirname;
|
||||||
|
|
||||||
let models = require('./models/index');
|
let models = require('./models/index');
|
||||||
|
let controllers = require('./controllers');
|
||||||
let db;
|
let db;
|
||||||
let {authenticationController} = require('./controllers');
|
|
||||||
|
|
||||||
|
|
||||||
var totalStorageUsed = null; // global variable that is regularly updated in the background to track the total used storage
|
// TODO
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function initializeStorage() {
|
|
||||||
var verifiedPath = mkDirByPathSync(config.storagePath, {isRelativeToScript: (config.storagePath.indexOf("/") === 0 ? false : true)});
|
|
||||||
if (verifiedPath != null)
|
|
||||||
logger.info("Verified storage path " + verifiedPath);
|
|
||||||
else {
|
|
||||||
logger.error("Unable to verify storage path '" + config.storagePath + "', check filesystem / permissions");
|
|
||||||
process.exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateJWTToken(token, publicKey) {
|
|
||||||
try {
|
|
||||||
var decoded = jwt.verify(token.replace("JWT ", ""), publicKey, {algorithms: ['RS256']});
|
|
||||||
return decoded;
|
|
||||||
} catch (exception) {
|
|
||||||
logger.error(exception);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatDate(timestampMs) {
|
|
||||||
return new Date(timestampMs).toISOString().replace(/T/, ' ').replace(/\..+/, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatDuration(durationSeconds) {
|
|
||||||
durationSeconds = Math.round(durationSeconds);
|
|
||||||
var secs = durationSeconds % 60;
|
|
||||||
var mins = Math.floor(durationSeconds / 60);
|
|
||||||
var hours = Math.floor(mins / 60);
|
|
||||||
mins = mins % 60;
|
|
||||||
|
|
||||||
var response = '';
|
|
||||||
if (hours > 0) response += hours + 'h ';
|
|
||||||
if (hours > 0 || mins > 0) response += mins + 'm ';
|
|
||||||
response += secs + 's';
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
function mkDirByPathSync(targetDir, {isRelativeToScript = false} = {}) {
|
|
||||||
const sep = path.sep;
|
|
||||||
const initDir = path.isAbsolute(targetDir) ? sep : '';
|
|
||||||
const baseDir = isRelativeToScript ? __dirname : '.';
|
|
||||||
|
|
||||||
return targetDir.split(sep).reduce((parentDir, childDir) => {
|
|
||||||
const curDir = path.resolve(baseDir, parentDir, childDir);
|
|
||||||
try {
|
|
||||||
fs.mkdirSync(curDir);
|
|
||||||
} catch (err) {
|
|
||||||
if (err.code === 'EEXIST') { // curDir already exists!
|
|
||||||
return curDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
// To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
|
|
||||||
if (err.code === 'ENOENT') { // Throw the original parentDir error on curDir `ENOENT` failure.
|
|
||||||
logger.error(`EACCES: permission denied, mkdir '${parentDir}'`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const caughtErr = ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1;
|
|
||||||
if (!caughtErr || (caughtErr && curDir === path.resolve(targetDir))) {
|
|
||||||
logger.error("'EACCES', 'EPERM', 'EISDIR' during mkdir");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return curDir;
|
|
||||||
}, initDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
function simpleStringify(object) {
|
|
||||||
var simpleObject = {};
|
|
||||||
for (var prop in object) {
|
|
||||||
if (!object.hasOwnProperty(prop)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (typeof (object[prop]) == 'object') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (typeof (object[prop]) == 'function') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
simpleObject[prop] = object[prop];
|
|
||||||
}
|
|
||||||
return JSON.stringify(simpleObject); // returns cleaned up JSON
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeFileSync(path, buffer, permission) {
|
|
||||||
var fileDescriptor;
|
|
||||||
try {
|
|
||||||
fileDescriptor = fs.openSync(path, 'w', permission);
|
|
||||||
} catch (e) {
|
|
||||||
fs.chmodSync(path, permission);
|
|
||||||
fileDescriptor = fs.openSync(path, 'w', permission);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileDescriptor) {
|
|
||||||
fs.writeSync(fileDescriptor, buffer, 0, buffer.length, 0);
|
|
||||||
fs.closeSync(fileDescriptor);
|
|
||||||
logger.info("writeFileSync wiriting to '" + path + "' successful");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
logger.error("writeFileSync writing to '" + path + "' failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function moveUploadedFile(buffer, directory, filename) {
|
|
||||||
logger.info("moveUploadedFile called with '" + filename + "' -> '" + directory + "'");
|
|
||||||
|
|
||||||
if (directory.indexOf("..") >= 0 || filename.indexOf("..") >= 0) {
|
|
||||||
logger.error("moveUploadedFile failed, .. in directory or filename");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.storagePath.lastIndexOf("/") !== config.storagePath.length - 1)
|
|
||||||
directory = '/' + directory;
|
|
||||||
if (directory.lastIndexOf("/") !== directory.length - 1)
|
|
||||||
directory = directory + '/';
|
|
||||||
|
|
||||||
var finalPath = mkDirByPathSync(config.storagePath + directory, {isRelativeToScript: (config.storagePath.indexOf("/") === 0 ? false : true)});
|
|
||||||
if (finalPath && finalPath.length > 0) {
|
|
||||||
if (writeFileSync(finalPath + "/" + filename, buffer, 0o660)) {
|
|
||||||
logger.info("moveUploadedFile successfully written '" + (finalPath + "/" + filename) + "'");
|
|
||||||
return finalPath + "/" + filename;
|
|
||||||
}
|
|
||||||
logger.error("moveUploadedFile failed to writeFileSync");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
logger.error("moveUploadedFile invalid final path, check permissions to create / write '" + (config.storagePath + directory) + "'");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getAuthenticatedAccount(req) {
|
|
||||||
|
|
||||||
var sessionCookie = (req.signedCookies !== undefined ? req.signedCookies.session : null);
|
|
||||||
if (!sessionCookie || sessionCookie.expires <= Date.now()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const account = await db.get('SELECT * FROM accounts WHERE LOWER(email) = ?', sessionCookie.account.trim().toLowerCase());
|
|
||||||
if (!account || account.banned) {
|
|
||||||
res.clearCookie('session');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const result = await db.run('UPDATE accounts SET last_ping = ? WHERE email = ?', Date.now(), account.email);
|
|
||||||
return account;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateTotalStorageUsed() {
|
|
||||||
var verifiedPath = mkDirByPathSync(config.storagePath, {isRelativeToScript: (config.storagePath.indexOf("/") === 0 ? false : true)});
|
|
||||||
if (verifiedPath !== null) {
|
|
||||||
totalStorageUsed = execSync("du -hs " + verifiedPath + " | awk -F'\t' '{print $1;}'").toString();
|
|
||||||
}
|
|
||||||
setTimeout(function () {
|
|
||||||
updateTotalStorageUsed();
|
|
||||||
}, 120000); // update the used storage each 120 seconds
|
|
||||||
}
|
|
||||||
|
|
||||||
function runAsyncWrapper(callback) {
|
function runAsyncWrapper(callback) {
|
||||||
return function (req, res, next) {
|
return function (req, res, next) {
|
||||||
callback(req, res, next)
|
callback(req, res, next)
|
||||||
|
@ -207,6 +40,8 @@ function runAsyncWrapper(callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// CREATE OUR SERVER EXPRESS APP
|
// CREATE OUR SERVER EXPRESS APP
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
|
@ -214,7 +49,8 @@ app.use(cookieParser(config.applicationSalt))
|
||||||
|
|
||||||
app.use('/favicon.ico', express.static('static/favicon.ico'));
|
app.use('/favicon.ico', express.static('static/favicon.ico'));
|
||||||
|
|
||||||
app.use(config.baseDriveDownloadPathMapping, express.static(config.storagePath));
|
//app.use(config.baseDriveDownloadPathMapping, express.static(config.storagePath));
|
||||||
|
|
||||||
app.use('/.well-known', express.static('.well-known'));
|
app.use('/.well-known', express.static('.well-known'));
|
||||||
|
|
||||||
// DRIVE & BOOT/CRASH LOG FILE UPLOAD HANDLING
|
// DRIVE & BOOT/CRASH LOG FILE UPLOAD HANDLING
|
||||||
|
@ -243,7 +79,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logger.info("HTTP.PUT /backend/post_upload permissions checked, calling moveUploadedFile");
|
logger.info("HTTP.PUT /backend/post_upload permissions checked, calling moveUploadedFile");
|
||||||
var moveResult = moveUploadedFile(buf, directory, filename);
|
var moveResult = controllers.storage.moveUploadedFile(buf, directory, filename);
|
||||||
if (moveResult === false) {
|
if (moveResult === false) {
|
||||||
logger.error("HTTP.PUT /backend/post_upload moveUploadedFile failed");
|
logger.error("HTTP.PUT /backend/post_upload moveUploadedFile failed");
|
||||||
res.status(500);
|
res.status(500);
|
||||||
|
@ -267,7 +103,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logger.info("HTTP.PUT /backend/post_upload permissions checked, calling moveUploadedFile");
|
logger.info("HTTP.PUT /backend/post_upload permissions checked, calling moveUploadedFile");
|
||||||
var moveResult = moveUploadedFile(buf, directory, filename);
|
var moveResult = controllers.storage.moveUploadedFile(buf, directory, filename);
|
||||||
if (moveResult === false) {
|
if (moveResult === false) {
|
||||||
logger.error("HTTP.PUT /backend/post_upload moveUploadedFile failed");
|
logger.error("HTTP.PUT /backend/post_upload moveUploadedFile failed");
|
||||||
res.status(500);
|
res.status(500);
|
||||||
|
@ -298,7 +134,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
return res.send('Unauthorized.').status(400)
|
return res.send('Unauthorized.').status(400)
|
||||||
}
|
}
|
||||||
|
|
||||||
let decoded = device.public_key ? await authenticationController.validateJWT(req.headers.authorization, device.public_key) : null;
|
let decoded = device.public_key ? await controllers.authentication.validateJWT(req.headers.authorization, device.public_key) : null;
|
||||||
|
|
||||||
if ((decoded == undefined || decoded.identity !== req.params.dongleId)) {
|
if ((decoded == undefined || decoded.identity !== req.params.dongleId)) {
|
||||||
logger.info(`HTTP.UPLOAD_URL JWT authorization failed, token: ${auth} device: ${JSON.stringify(device)}, decoded: ${JSON.stringify(decoded)}`);
|
logger.info(`HTTP.UPLOAD_URL JWT authorization failed, token: ${auth} device: ${JSON.stringify(device)}, decoded: ${JSON.stringify(decoded)}`);
|
||||||
|
@ -423,7 +259,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var decoded = validateJWTToken(req.query.register_token, public_key);
|
var decoded = controllers.authentication.validateJWT(req.query.register_token, public_key);
|
||||||
|
|
||||||
if (decoded == null || decoded.register == undefined) {
|
if (decoded == null || decoded.register == undefined) {
|
||||||
logger.error("HTTP.V2.PILOTAUTH JWT token is invalid (" + JSON.stringify(decoded) + ")");
|
logger.error("HTTP.V2.PILOTAUTH JWT token is invalid (" + JSON.stringify(decoded) + ")");
|
||||||
|
@ -542,7 +378,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
|
|
||||||
|
|
||||||
app.get('/useradmin', runAsyncWrapper(async (req, res) => {
|
app.get('/useradmin', runAsyncWrapper(async (req, res) => {
|
||||||
const account = await getAuthenticatedAccount(req);
|
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||||
if (account != null) {
|
if (account != null) {
|
||||||
res.redirect('/useradmin/overview');
|
res.redirect('/useradmin/overview');
|
||||||
return;
|
return;
|
||||||
|
@ -565,7 +401,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
'Accounts: ' + accounts.num + ' | ' +
|
'Accounts: ' + accounts.num + ' | ' +
|
||||||
'Devices: ' + devices.num + ' | ' +
|
'Devices: ' + devices.num + ' | ' +
|
||||||
'Drives: ' + drives.num + ' | ' +
|
'Drives: ' + drives.num + ' | ' +
|
||||||
'Storage Used: ' + (totalStorageUsed !== null ? totalStorageUsed : '--') + '<br><br>' + config.welcomeMessage + '</html>');
|
'Storage Used: ' + (await controllers.storage.getTotalStorageUsed() !== null ? await controllers.storage.getTotalStorageUsed() : '--') + '<br><br>' + config.welcomeMessage + '</html>');
|
||||||
})),
|
})),
|
||||||
|
|
||||||
|
|
||||||
|
@ -576,7 +412,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const authAccount = await getAuthenticatedAccount(req);
|
const authAccount = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||||
if (authAccount != null) {
|
if (authAccount != null) {
|
||||||
res.redirect('/useradmin/overview');
|
res.redirect('/useradmin/overview');
|
||||||
return;
|
return;
|
||||||
|
@ -657,7 +493,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const account = await getAuthenticatedAccount(req);
|
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||||
if (account != null) {
|
if (account != null) {
|
||||||
res.redirect('/useradmin/overview');
|
res.redirect('/useradmin/overview');
|
||||||
return;
|
return;
|
||||||
|
@ -678,7 +514,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
|
|
||||||
|
|
||||||
app.get('/useradmin/overview', runAsyncWrapper(async (req, res) => {
|
app.get('/useradmin/overview', runAsyncWrapper(async (req, res) => {
|
||||||
const account = await getAuthenticatedAccount(req);
|
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
||||||
return;
|
return;
|
||||||
|
@ -691,14 +527,14 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
`<br><br><h3>Account Overview</h3>
|
`<br><br><h3>Account Overview</h3>
|
||||||
<b>Account:</b> #` + account.id + `<br>
|
<b>Account:</b> #` + account.id + `<br>
|
||||||
<b>Email:</b> ` + account.email + `<br>
|
<b>Email:</b> ` + account.email + `<br>
|
||||||
<b>Created:</b> ` + formatDate(account.created) + `<br><br>
|
<b>Created:</b> ` + controllers.helpers.formatDate(account.created) + `<br><br>
|
||||||
<b>Devices:</b><br>
|
<b>Devices:</b><br>
|
||||||
<table border=1 cellpadding=2 cellspacing=2>
|
<table border=1 cellpadding=2 cellspacing=2>
|
||||||
<tr><th>dongle_id</th><th>device_type</th><th>created</th><th>last_ping</th><th>storage_used</th></tr>
|
<tr><th>dongle_id</th><th>device_type</th><th>created</th><th>last_ping</th><th>storage_used</th></tr>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
for (var i in devices) {
|
for (var i in devices) {
|
||||||
response += '<tr><td><a href="/useradmin/device/' + devices[i].dongle_id + '">' + devices[i].dongle_id + '</a></td><td>' + devices[i].device_type + '</td><td>' + formatDate(devices[i].created) + '</td><td>' + formatDate(devices[i].last_ping) + '</td><td>' + devices[i].storage_used + ' MB</td></tr>';
|
response += '<tr><td><a href="/useradmin/device/' + devices[i].dongle_id + '">' + devices[i].dongle_id + '</a></td><td>' + devices[i].device_type + '</td><td>' + controllers.helpers.formatDate(devices[i].created) + '</td><td>' + controllers.helpers.formatDate(devices[i].last_ping) + '</td><td>' + devices[i].storage_used + ' MB</td></tr>';
|
||||||
}
|
}
|
||||||
response += `</table>
|
response += `</table>
|
||||||
<br>
|
<br>
|
||||||
|
@ -720,7 +556,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
|
|
||||||
|
|
||||||
app.get('/useradmin/unpair_device/:dongleId', runAsyncWrapper(async (req, res) => {
|
app.get('/useradmin/unpair_device/:dongleId', runAsyncWrapper(async (req, res) => {
|
||||||
const account = await getAuthenticatedAccount(req);
|
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
||||||
return;
|
return;
|
||||||
|
@ -745,7 +581,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
|
|
||||||
|
|
||||||
app.post('/useradmin/pair_device', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
app.post('/useradmin/pair_device', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||||
const account = await getAuthenticatedAccount(req);
|
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
||||||
return;
|
return;
|
||||||
|
@ -757,7 +593,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
res.redirect('/useradmin/overview?linkstatus=' + encodeURIComponent('Device not registered on Server'));
|
res.redirect('/useradmin/overview?linkstatus=' + encodeURIComponent('Device not registered on Server'));
|
||||||
}
|
}
|
||||||
var decoded = validateJWTToken(qrCodeParts[2], device.public_key);
|
var decoded = controllers.authentication.validateJWT(qrCodeParts[2], device.public_key);
|
||||||
if (decoded == null || decoded.pair == undefined) {
|
if (decoded == null || decoded.pair == undefined) {
|
||||||
res.redirect('/useradmin/overview?linkstatus=' + encodeURIComponent('Device QR Token is invalid or has expired'));
|
res.redirect('/useradmin/overview?linkstatus=' + encodeURIComponent('Device QR Token is invalid or has expired'));
|
||||||
}
|
}
|
||||||
|
@ -776,7 +612,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
|
|
||||||
|
|
||||||
app.get('/useradmin/device/:dongleId', runAsyncWrapper(async (req, res) => {
|
app.get('/useradmin/device/:dongleId', runAsyncWrapper(async (req, res) => {
|
||||||
const account = await getAuthenticatedAccount(req);
|
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
||||||
return;
|
return;
|
||||||
|
@ -836,8 +672,8 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
<b>Type:</b> ` + device.device_type + `<br>
|
<b>Type:</b> ` + device.device_type + `<br>
|
||||||
<b>Serial:</b> ` + device.serial + `<br>
|
<b>Serial:</b> ` + device.serial + `<br>
|
||||||
<b>IMEI:</b> ` + device.imei + `<br>
|
<b>IMEI:</b> ` + device.imei + `<br>
|
||||||
<b>Registered:</b> ` + formatDate(device.created) + `<br>
|
<b>Registered:</b> ` + controllers.helpers.formatDate(device.created) + `<br>
|
||||||
<b>Last Ping:</b> ` + formatDate(device.last_ping) + `<br>
|
<b>Last Ping:</b> ` + controllers.helpers.formatDate(device.last_ping) + `<br>
|
||||||
<b>Public Key:</b><br><span style="font-size: 0.8em">` + device.public_key.replace(/\r?\n|\r/g, "<br>") + `</span>
|
<b>Public Key:</b><br><span style="font-size: 0.8em">` + device.public_key.replace(/\r?\n|\r/g, "<br>") + `</span>
|
||||||
<br>
|
<br>
|
||||||
<b>Stored Drives:</b> ` + drives.length + `<br>
|
<b>Stored Drives:</b> ` + drives.length + `<br>
|
||||||
|
@ -850,7 +686,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
<tr><th>date</th><th>file</th><th>size</th></tr>
|
<tr><th>date</th><th>file</th><th>size</th></tr>
|
||||||
`;
|
`;
|
||||||
for (var i = 0; i < Math.min(5, bootlogFiles.length); i++) {
|
for (var i = 0; i < Math.min(5, bootlogFiles.length); i++) {
|
||||||
response += `<tr><td>` + formatDate(bootlogFiles[i].date) + `</td><td><a href="` + config.baseDriveDownloadUrl + device.dongle_id + "/" + dongleIdHash + "/boot/" + bootlogFiles[i].name + `" target=_blank>` + bootlogFiles[i].name + `</a></td><td>` + bootlogFiles[i].size + `</td></tr>`;
|
response += `<tr><td>` + controllers.helpers.formatDate(bootlogFiles[i].date) + `</td><td><a href="` + config.baseDriveDownloadUrl + device.dongle_id + "/" + dongleIdHash + "/boot/" + bootlogFiles[i].name + `" target=_blank>` + bootlogFiles[i].name + `</a></td><td>` + bootlogFiles[i].size + `</td></tr>`;
|
||||||
}
|
}
|
||||||
response += `</table><br><br>`;
|
response += `</table><br><br>`;
|
||||||
|
|
||||||
|
@ -859,7 +695,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
<tr><th>date</th><th>file</th><th>size</th></tr>
|
<tr><th>date</th><th>file</th><th>size</th></tr>
|
||||||
`;
|
`;
|
||||||
for (var i = 0; i < Math.min(5, crashlogFiles.length); i++) {
|
for (var i = 0; i < Math.min(5, crashlogFiles.length); i++) {
|
||||||
response += `<tr><td>` + formatDate(crashlogFiles[i].date) + `</td><td><a href="` + config.baseDriveDownloadUrl + device.dongle_id + "/" + dongleIdHash + "/crash/" + crashlogFiles[i].name + `" target=_blank>` + crashlogFiles[i].name + `</a></td><td>` + crashlogFiles[i].size + `</td></tr>`;
|
response += `<tr><td>` + controllers.helpers.formatDate(crashlogFiles[i].date) + `</td><td><a href="` + config.baseDriveDownloadUrl + device.dongle_id + "/" + dongleIdHash + "/crash/" + crashlogFiles[i].name + `" target=_blank>` + crashlogFiles[i].name + `</a></td><td>` + crashlogFiles[i].size + `</td></tr>`;
|
||||||
}
|
}
|
||||||
response += `</table><br><br>`;
|
response += `</table><br><br>`;
|
||||||
|
|
||||||
|
@ -870,7 +706,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
`;
|
`;
|
||||||
|
|
||||||
for (var i in drives) {
|
for (var i in drives) {
|
||||||
response += '<tr><td><a href="/useradmin/drive/' + drives[i].dongle_id + '/' + drives[i].identifier + '">' + (drives[i].is_preserved ? '<b>' : '') + drives[i].identifier + (drives[i].is_preserved ? '</b>' : '') + '</a></td><td>' + Math.round(drives[i].filesize / 1024) + ' MiB</td><td>' + formatDuration(drives[i].duration) + '</td><td>' + Math.round(drives[i].distance_meters / 1000) + ' km</td><td>' + drives[i].upload_complete + '</td><td>' + drives[i].is_processed + '</td><td>' + formatDate(drives[i].created) + '</td><td>' + '[<a href="/useradmin/drive/' + drives[i].dongle_id + '/' + drives[i].identifier + '/delete" onclick="return confirm(\'Permanently delete this drive?\')">delete</a>]' + (drives[i].is_preserved ? '' : ' [<a href="/useradmin/drive/' + drives[i].dongle_id + '/' + drives[i].identifier + '/preserve">preserve</a>]') + '</tr>';
|
response += '<tr><td><a href="/useradmin/drive/' + drives[i].dongle_id + '/' + drives[i].identifier + '">' + (drives[i].is_preserved ? '<b>' : '') + drives[i].identifier + (drives[i].is_preserved ? '</b>' : '') + '</a></td><td>' + Math.round(drives[i].filesize / 1024) + ' MiB</td><td>' + controllers.helpers.formatDuration(drives[i].duration) + '</td><td>' + Math.round(drives[i].distance_meters / 1000) + ' km</td><td>' + drives[i].upload_complete + '</td><td>' + drives[i].is_processed + '</td><td>' + controllers.helpers.formatDate(drives[i].created) + '</td><td>' + '[<a href="/useradmin/drive/' + drives[i].dongle_id + '/' + drives[i].identifier + '/delete" onclick="return confirm(\'Permanently delete this drive?\')">delete</a>]' + (drives[i].is_preserved ? '' : ' [<a href="/useradmin/drive/' + drives[i].dongle_id + '/' + drives[i].identifier + '/preserve">preserve</a>]') + '</tr>';
|
||||||
}
|
}
|
||||||
response += `</table>
|
response += `</table>
|
||||||
<br>
|
<br>
|
||||||
|
@ -887,7 +723,7 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
|
|
||||||
|
|
||||||
app.get('/useradmin/drive/:dongleId/:driveIdentifier/:action', runAsyncWrapper(async (req, res) => {
|
app.get('/useradmin/drive/:dongleId/:driveIdentifier/:action', runAsyncWrapper(async (req, res) => {
|
||||||
const account = await getAuthenticatedAccount(req);
|
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
||||||
return;
|
return;
|
||||||
|
@ -927,7 +763,8 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
|
|
||||||
|
|
||||||
app.get('/useradmin/drive/:dongleId/:driveIdentifier', runAsyncWrapper(async (req, res) => {
|
app.get('/useradmin/drive/:dongleId/:driveIdentifier', runAsyncWrapper(async (req, res) => {
|
||||||
const account = await getAuthenticatedAccount(req);
|
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||||
|
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
||||||
return;
|
return;
|
||||||
|
@ -966,11 +803,11 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
`
|
`
|
||||||
<a href="/useradmin/device/` + device.dongle_id + `">< < < Back To Device ` + device.dongle_id + `</a>
|
<a href="/useradmin/device/` + device.dongle_id + `">< < < Back To Device ` + device.dongle_id + `</a>
|
||||||
<br><br><h3>Drive ` + drive.identifier + ` on ` + drive.dongle_id + `</h3>
|
<br><br><h3>Drive ` + drive.identifier + ` on ` + drive.dongle_id + `</h3>
|
||||||
<b>Drive Date:</b> ` + formatDate(drive.drive_date) + `<br>
|
<b>Drive Date:</b> ` + controllers.helpers.formatDate(drive.drive_date) + `<br>
|
||||||
<b>Upload Date:</b> ` + formatDate(drive.created) + `<br>
|
<b>Upload Date:</b> ` + controllers.helpers.formatDate(drive.created) + `<br>
|
||||||
<b>Num Segments:</b> ` + (drive.max_segment + 1) + `<br>
|
<b>Num Segments:</b> ` + (drive.max_segment + 1) + `<br>
|
||||||
<b>Storage:</b> ` + Math.round(drive.filesize / 1024) + ` MiB<br>
|
<b>Storage:</b> ` + Math.round(drive.filesize / 1024) + ` MiB<br>
|
||||||
<b>Duration:</b> ` + formatDuration(drive.duration) + `<br>
|
<b>Duration:</b> ` + controllers.helpers.formatDuration(drive.duration) + `<br>
|
||||||
<b>Distance:</b> ` + Math.round(drive.distance_meters / 1000) + ` km<br>
|
<b>Distance:</b> ` + Math.round(drive.distance_meters / 1000) + ` km<br>
|
||||||
<b>Is Preserved:</b> ` + drive.is_preserved + `<br>
|
<b>Is Preserved:</b> ` + drive.is_preserved + `<br>
|
||||||
<b>Upload Complete:</b> ` + drive.upload_complete + `<br>
|
<b>Upload Complete:</b> ` + drive.upload_complete + `<br>
|
||||||
|
@ -1043,23 +880,23 @@ app.put('/backend/post_upload', bodyParser.raw({
|
||||||
})),
|
})),
|
||||||
|
|
||||||
|
|
||||||
app.get('/', runAsyncWrapper(async (req, res) => {
|
app.get('/', async (req, res) => {
|
||||||
res.status(404);
|
res.status(404);
|
||||||
var response = '<html style="font-family: monospace"><h2>404 Not found</h2>' +
|
var response = '<html style="font-family: monospace"><h2>404 Not found</h2>' +
|
||||||
'Are you looking for the <a href="/useradmin">useradmin dashboard</a>?';
|
'Are you looking for the <a href="/useradmin">useradmin dashboard</a>?';
|
||||||
res.send(response);
|
res.send(response);
|
||||||
})),
|
}),
|
||||||
|
|
||||||
|
|
||||||
app.get('*', runAsyncWrapper(async (req, res) => {
|
app.get('*', runAsyncWrapper(async (req, res) => {
|
||||||
logger.error("HTTP.GET unhandled request: " + simpleStringify(req) + ", " + simpleStringify(res) + "")
|
logger.error("HTTP.GET unhandled request: " + controllers.helpers.simpleStringify(req) + ", " + controllers.helpers.simpleStringify(res) + "")
|
||||||
res.status(400);
|
res.status(400);
|
||||||
res.send('Not Implemented');
|
res.send('Not Implemented');
|
||||||
})),
|
})),
|
||||||
|
|
||||||
|
|
||||||
app.post('*', runAsyncWrapper(async (req, res) => {
|
app.post('*', runAsyncWrapper(async (req, res) => {
|
||||||
logger.error("HTTP.POST unhandled request: " + simpleStringify(req) + ", " + simpleStringify(res) + "")
|
logger.error("HTTP.POST unhandled request: " + controllers.helpers.simpleStringify(req) + ", " + controllers.helpers.simpleStringify(res) + "")
|
||||||
res.status(400);
|
res.status(400);
|
||||||
res.send('Not Implemented');
|
res.send('Not Implemented');
|
||||||
}));
|
}));
|
||||||
|
@ -1076,9 +913,12 @@ lockfile.lock('retropilot_server.lock', {realpath: false, stale: 30000, update:
|
||||||
db = _models.db;
|
db = _models.db;
|
||||||
models = _models.models;
|
models = _models.models;
|
||||||
|
|
||||||
|
const _controllers = await controllers(models, logger);
|
||||||
|
controllers = _controllers;
|
||||||
|
|
||||||
initializeStorage();
|
|
||||||
updateTotalStorageUsed();
|
controllers.storage.initializeStorage();
|
||||||
|
await controllers.storage.updateTotalStorageUsed();
|
||||||
|
|
||||||
var privateKey = fs.readFileSync(config.sslKey, 'utf8');
|
var privateKey = fs.readFileSync(config.sslKey, 'utf8');
|
||||||
var certificate = fs.readFileSync(config.sslCrt, 'utf8');
|
var certificate = fs.readFileSync(config.sslCrt, 'utf8');
|
||||||
|
|
Loading…
Reference in New Issue