apply eslint fixes
parent
4f13eae80a
commit
7b43aa3eff
|
@ -1,61 +1,60 @@
|
|||
var config = {
|
||||
applicationSalt: 'RANDOM_SEED',
|
||||
|
||||
databaseFile: 'database.sqlite',
|
||||
|
||||
allowAccountRegistration: true,
|
||||
|
||||
httpInterface: '0.0.0.0',
|
||||
httpPort: 3000,
|
||||
|
||||
httpsInterface: '0.0.0.0',
|
||||
httpsPort: 4430,
|
||||
sslKey: 'certs/retropilot.key',
|
||||
sslCrt: 'certs/retropilot.crt',
|
||||
applicationSalt: 'RANDOM_SEED',
|
||||
|
||||
canSendMail: true, // Skips sending mail, all attempted mail is logged under DEBUG
|
||||
smtpHost: "localhost", // credentials for smtp server to send account registration mails. if not filled in, get the generated tokens from the server.log manually
|
||||
smtpPort: 25,
|
||||
smtpUser: "root",
|
||||
smtpPassword: "",
|
||||
smtpFrom: "no-reply@retropilot.org",
|
||||
databaseFile: 'database.sqlite',
|
||||
|
||||
baseUrl: 'http://192.168.1.165:3000/', // base url of the retropilot server
|
||||
baseUploadUrl: 'http://192.168.1.165:3000/backend/post_upload', // base url sent to devices for POSTing drives & logs
|
||||
|
||||
baseDriveDownloadUrl: 'http://192.168.1.165:3000/realdata/', // base download url for drive & log data
|
||||
baseDriveDownloadPathMapping: '/realdata', // path mapping of above download url for expressjs, prefix with "/"
|
||||
storagePath: 'realdata/', // relative or absolute ( "/..." for absolute path )
|
||||
allowAccountRegistration: true,
|
||||
|
||||
cabanaUrl: 'http://192.168.1.165:3000/cabana/index.html',
|
||||
httpInterface: '0.0.0.0',
|
||||
httpPort: 3000,
|
||||
|
||||
deviceStorageQuotaMb: 200000,
|
||||
deviceDriveExpirationDays: 30,
|
||||
|
||||
httpsInterface: '0.0.0.0',
|
||||
httpsPort: 4430,
|
||||
sslKey: 'certs/retropilot.key',
|
||||
sslCrt: 'certs/retropilot.crt',
|
||||
|
||||
welcomeMessage: `<><><><><><><><><><><><><><><><><><><><><><><br>2021 RetroPilot`,
|
||||
canSendMail: true, // Skips sending mail, all attempted mail is logged under DEBUG
|
||||
smtpHost: 'localhost', // credentials for smtp server to send account registration mails. if not filled in, get the generated tokens from the server.log manually
|
||||
smtpPort: 25,
|
||||
smtpUser: 'root',
|
||||
smtpPassword: '',
|
||||
smtpFrom: 'no-reply@retropilot.org',
|
||||
|
||||
flags: {
|
||||
useUserAdminApi: false,
|
||||
baseUrl: 'http://192.168.1.165:3000/', // base url of the retropilot server
|
||||
baseUploadUrl: 'http://192.168.1.165:3000/backend/post_upload', // base url sent to devices for POSTing drives & logs
|
||||
|
||||
baseDriveDownloadUrl: 'http://192.168.1.165:3000/realdata/', // base download url for drive & log data
|
||||
baseDriveDownloadPathMapping: '/realdata', // path mapping of above download url for expressjs, prefix with "/"
|
||||
storagePath: 'realdata/', // relative or absolute ( "/..." for absolute path )
|
||||
|
||||
cabanaUrl: 'http://192.168.1.165:3000/cabana/index.html',
|
||||
|
||||
deviceStorageQuotaMb: 200000,
|
||||
deviceDriveExpirationDays: 30,
|
||||
|
||||
welcomeMessage: '<><><><><><><><><><><><><><><><><><><><><><><br>2021 RetroPilot',
|
||||
|
||||
flags: {
|
||||
useUserAdminApi: false,
|
||||
},
|
||||
|
||||
clientSocket: { // Used in development, remove before prod
|
||||
port: 81,
|
||||
host: '0.0.0.0',
|
||||
|
||||
},
|
||||
|
||||
athena: {
|
||||
enabled: true, // Enables Athena service
|
||||
secure: true, // Disables crypto on Websocket server - use for testing on local network, change ATHENA_HOST in openpilot to ws:// instead of wss://
|
||||
api: {
|
||||
ratelimit: 100, // Maxmium hits to /realtime/* per 30s
|
||||
},
|
||||
|
||||
clientSocket: { // Used in development, remove before prod
|
||||
port: 81,
|
||||
host: "0.0.0.0"
|
||||
|
||||
socket: {
|
||||
port: 4040,
|
||||
heartbeatFrequency: 5000, // Higher the number = lower traffic, varies on how many devices are connected
|
||||
},
|
||||
|
||||
athena: {
|
||||
enabled: true, // Enables Athena service
|
||||
secure: true, // Disables crypto on Websocket server - use for testing on local network, change ATHENA_HOST in openpilot to ws:// instead of wss://
|
||||
api: {
|
||||
ratelimit: 100 // Maxmium hits to /realtime/* per 30s
|
||||
},
|
||||
socket: {
|
||||
port: 4040,
|
||||
heartbeatFrequency: 5000 // Higher the number = lower traffic, varies on how many devices are connected
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
|
|
@ -25,14 +25,13 @@ async function banAccount(ban, userId) {
|
|||
let cleanBan;
|
||||
if (ban === 'true' || ban === 'false') {
|
||||
cleanBan = ban === 'true';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return { success: false, status: 400, data: { bad_data: true } };
|
||||
}
|
||||
|
||||
const update = await models_orm.models.accounts.update(
|
||||
{ banned: cleanBan ? 1 : 0 },
|
||||
{ where: { id: userId } }
|
||||
{ where: { id: userId } },
|
||||
);
|
||||
|
||||
const verify = await models_orm.models.accounts.findOne({ where: { id: userId } });
|
||||
|
@ -45,5 +44,5 @@ async function banAccount(ban, userId) {
|
|||
|
||||
module.exports = {
|
||||
banAccount,
|
||||
isCurrentUserAdmin
|
||||
isCurrentUserAdmin,
|
||||
};
|
||||
|
|
|
@ -8,8 +8,7 @@ const config = require('../config');
|
|||
async function validateJWT(token, key) {
|
||||
try {
|
||||
return jsonwebtoken.verify(token.replace('JWT ', ''), key, { algorithms: ['RS256'], ignoreNotBefore: true });
|
||||
}
|
||||
catch (exception) {
|
||||
} catch (exception) {
|
||||
console.log(`failed to validate JWT ${exception}`);
|
||||
}
|
||||
return null;
|
||||
|
@ -18,8 +17,7 @@ async function validateJWT(token, key) {
|
|||
async function readJWT(token) {
|
||||
try {
|
||||
return jsonwebtoken.decode(token);
|
||||
}
|
||||
catch (exception) {
|
||||
} catch (exception) {
|
||||
logger.warn(`failed to read JWT ${exception}`);
|
||||
}
|
||||
return null;
|
||||
|
@ -54,7 +52,7 @@ async function changePassword(account, newPassword, oldPassword) {
|
|||
|
||||
const update = models_orm.models.accounts.update(
|
||||
{ password: newPasswordHash },
|
||||
{ where: { id: account.id } }
|
||||
{ where: { id: account.id } },
|
||||
);
|
||||
|
||||
return { success: true, msg: 'PASSWORD CHANGED', changed: true };
|
||||
|
@ -80,8 +78,7 @@ async function getAccountFromJWT(jwt, limitData) {
|
|||
|
||||
try {
|
||||
token = jsonwebtoken.verify(jwt, config.applicationSalt);
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
return null;// {success: false, msg: 'BAD_JWT'}
|
||||
}
|
||||
|
||||
|
@ -94,7 +91,7 @@ async function getAccountFromJWT(jwt, limitData) {
|
|||
if (account.dataValues) {
|
||||
const update = models_orm.models.accounts.update(
|
||||
{ last_ping: Date.now() },
|
||||
{ where: { id: account.id } }
|
||||
{ where: { id: account.id } },
|
||||
);
|
||||
|
||||
if (!account || account.banned) {
|
||||
|
@ -113,5 +110,5 @@ module.exports = {
|
|||
changePassword,
|
||||
signIn,
|
||||
readJWT,
|
||||
getAccountFromJWT
|
||||
getAccountFromJWT,
|
||||
};
|
||||
|
|
|
@ -21,14 +21,12 @@ async function pairDevice(account, qr_string) {
|
|||
if (qrCodeParts.length > 1) {
|
||||
deviceQuery = await models_orm.models.device.findOne({ where: { serial: qrCodeParts[1] } });
|
||||
pairJWT = qrCodeParts[2];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pairJWT = qr_string;
|
||||
const data = await authenticationController.readJWT(qr_string);
|
||||
if (data.pair === true) {
|
||||
deviceQuery = await models_orm.models.device.findOne({ where: { dongle_id: data.identity } });
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return { success: false, noPair: true };
|
||||
}
|
||||
}
|
||||
|
@ -52,15 +50,15 @@ async function pairDevice(account, qr_string) {
|
|||
async function pairDeviceToAccountId(dongle_id, account_id) {
|
||||
const update = await models_orm.models.device.update(
|
||||
{ account_id },
|
||||
{ where: { dongle_id } }
|
||||
{ where: { dongle_id } },
|
||||
);
|
||||
|
||||
const check = await models_orm.models.device.findOne(
|
||||
{ where: { dongle_id, account_id } }
|
||||
{ where: { dongle_id, account_id } },
|
||||
);
|
||||
if (check.dataValues) {
|
||||
return {
|
||||
success: true, paired: true, dongle_id, account_id
|
||||
success: true, paired: true, dongle_id, account_id,
|
||||
};
|
||||
}
|
||||
return { success: false, paired: false };
|
||||
|
@ -68,13 +66,13 @@ async function pairDeviceToAccountId(dongle_id, account_id) {
|
|||
|
||||
async function unpairDevice(account, dongleId) {
|
||||
const device = await models_orm.models.device.getOne(
|
||||
{ where: { account_id: account.id, dongle_id: dongleId } }
|
||||
{ where: { account_id: account.id, dongle_id: dongleId } },
|
||||
);
|
||||
|
||||
if (device && device.dataValues) {
|
||||
await models_orm.models.device.update(
|
||||
{ account_id: 0 },
|
||||
{ where: { dongle_id: dongleId } }
|
||||
{ where: { dongle_id: dongleId } },
|
||||
);
|
||||
return { success: true };
|
||||
}
|
||||
|
@ -83,7 +81,7 @@ async function unpairDevice(account, dongleId) {
|
|||
|
||||
async function setDeviceNickname(account, dongleId, nickname) {
|
||||
const device = await models_orm.models.device.getOne(
|
||||
{ where: { account_id: account.id, dongle_id: dongleId } }
|
||||
{ where: { account_id: account.id, dongle_id: dongleId } },
|
||||
);
|
||||
|
||||
const cleanNickname = sanitize.value(nickname, 'string');
|
||||
|
@ -91,7 +89,7 @@ async function setDeviceNickname(account, dongleId, nickname) {
|
|||
if (device && device.dataValues) {
|
||||
await models_orm.models.device.update(
|
||||
{ nickname: cleanNickname },
|
||||
{ where: { dongle_id: dongleId } }
|
||||
{ where: { dongle_id: dongleId } },
|
||||
);
|
||||
return { success: true, data: { nickname: cleanNickname } };
|
||||
}
|
||||
|
@ -112,7 +110,7 @@ async function getDeviceFromDongle(dongleId) {
|
|||
async function setIgnoredUploads(dongleId, isIgnored) {
|
||||
const update = models_orm.models.accounts.update(
|
||||
{ dongle_id: dongleId },
|
||||
{ where: { uploads_ignored: isIgnored } }
|
||||
{ where: { uploads_ignored: isIgnored } },
|
||||
);
|
||||
|
||||
// TODO check this change was processed..
|
||||
|
@ -128,7 +126,7 @@ async function getAllDevicesFiltered() {
|
|||
async function updateLastPing(device_id, dongle_id) {
|
||||
models_orm.models.device.update(
|
||||
{ last_ping: Date.now() },
|
||||
{ where: { [Op.or]: [{ id: device_id }, { dongle_id }] } }
|
||||
{ where: { [Op.or]: [{ id: device_id }, { dongle_id }] } },
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -150,8 +148,8 @@ async function isUserAuthorised(account_id, dongle_id) {
|
|||
return {
|
||||
success: true,
|
||||
data: {
|
||||
authorised: true, account_id: account.id, dongle_id: device.dongle_id
|
||||
}
|
||||
authorised: true, account_id: account.id, dongle_id: device.dongle_id,
|
||||
},
|
||||
};
|
||||
}
|
||||
return { success: false, msg: 'not_authorised', data: { authorised: false, account_id: account.id, dongle_id: device.dongle_id } };
|
||||
|
@ -199,15 +197,14 @@ async function getCrashlogs(dongle_id) {
|
|||
let dateObj = null;
|
||||
try {
|
||||
dateObj = Date.parse(timeString);
|
||||
}
|
||||
catch (exception) {}
|
||||
} catch (exception) {}
|
||||
if (!dateObj) dateObj = new Date(0);
|
||||
|
||||
crashlogFiles.push({
|
||||
name: crashlogDirectoryTree.children[i].name,
|
||||
size: crashlogDirectoryTree.children[i].size,
|
||||
date: dateObj,
|
||||
permalink: `${config.baseDriveDownloadUrl}${dongle_id}/${dongleIdHash}/crash/${crashlogDirectoryTree.children[i].name}`
|
||||
permalink: `${config.baseDriveDownloadUrl}${dongle_id}/${dongleIdHash}/crash/${crashlogDirectoryTree.children[i].name}`,
|
||||
});
|
||||
}
|
||||
crashlogFiles.sort((a, b) => ((a.date < b.date) ? 1 : -1));
|
||||
|
@ -228,15 +225,14 @@ async function getBootlogs(dongle_id) {
|
|||
let dateObj = null;
|
||||
try {
|
||||
dateObj = Date.parse(timeString);
|
||||
}
|
||||
catch (exception) {}
|
||||
} catch (exception) {}
|
||||
if (!dateObj) dateObj = new Date(0);
|
||||
|
||||
bootlogFiles.push({
|
||||
name: bootlogDirectoryTree.children[i].name,
|
||||
size: bootlogDirectoryTree.children[i].size,
|
||||
date: dateObj,
|
||||
permalink: `${config.baseDriveDownloadUrl}${dongle_id}/${dongleIdHash}/boot/${bootlogDirectoryTree.children[i].name}`
|
||||
permalink: `${config.baseDriveDownloadUrl}${dongle_id}/${dongleIdHash}/boot/${bootlogDirectoryTree.children[i].name}`,
|
||||
});
|
||||
}
|
||||
bootlogFiles.sort((a, b) => ((a.date < b.date) ? 1 : -1));
|
||||
|
@ -261,5 +257,5 @@ module.exports = {
|
|||
// drive stuff, move maybe?
|
||||
getDrives,
|
||||
getBootlogs,
|
||||
getCrashlogs
|
||||
getCrashlogs,
|
||||
};
|
||||
|
|
|
@ -39,5 +39,5 @@ function formatDate(timestampMs) {
|
|||
}
|
||||
|
||||
module.exports = {
|
||||
formatDuration, simpleStringify, formatDate
|
||||
formatDuration, simpleStringify, formatDate,
|
||||
};
|
||||
|
|
|
@ -9,5 +9,5 @@ module.exports = async (models, logger, models_sqli) => ({
|
|||
mailing: require('./mailing')(models, logger),
|
||||
users: require('./users'),
|
||||
admin: require('./admin'),
|
||||
devices: require('./devices')
|
||||
devices: require('./devices'),
|
||||
});
|
||||
|
|
|
@ -10,12 +10,12 @@ const transporter = nodemailer.createTransport(
|
|||
port: config.smtpPort,
|
||||
auth: {
|
||||
user: config.smtpUser,
|
||||
pass: config.smtpPassword
|
||||
pass: config.smtpPassword,
|
||||
},
|
||||
logger: true,
|
||||
debug: false
|
||||
debug: false,
|
||||
},
|
||||
{ from: config.smtpFrom }
|
||||
{ from: config.smtpFrom },
|
||||
);
|
||||
|
||||
async function sendEmailVerification(token, email) {
|
||||
|
@ -30,12 +30,11 @@ async function sendEmailVerification(token, email) {
|
|||
from: config.smtpFrom,
|
||||
to: email.trim(),
|
||||
subject: 'RetroPilot Registration Token',
|
||||
text: `Your Email Registration Token Is: "${token}"`
|
||||
text: `Your Email Registration Token Is: "${token}"`,
|
||||
};
|
||||
|
||||
error, info = await transporter.sendMail(message);
|
||||
}
|
||||
catch (exception) {
|
||||
} catch (exception) {
|
||||
logger.warn(`Email to ${email} FAILED ${exception} - ${token}`);
|
||||
}
|
||||
|
||||
|
@ -52,6 +51,6 @@ module.exports = (_models, _logger) => {
|
|||
logger = _logger;
|
||||
|
||||
return {
|
||||
sendEmailVerification
|
||||
sendEmailVerification,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -12,8 +12,7 @@ function initializeStorage() {
|
|||
var verifiedPath = mkDirByPathSync(config.storagePath, { isRelativeToScript: (config.storagePath.indexOf('/') !== 0) });
|
||||
if (verifiedPath != null) {
|
||||
logger.info(`Verified storage path ${verifiedPath}`);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
logger.error(`Unable to verify storage path '${config.storagePath}', check filesystem / permissions`);
|
||||
process.exit();
|
||||
}
|
||||
|
@ -29,8 +28,7 @@ function mkDirByPathSync(targetDir, { isRelativeToScript = false } = {}) {
|
|||
const curDir = path.resolve(baseDir, parentDir, childDir);
|
||||
try {
|
||||
fs.mkdirSync(curDir);
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
// console.debug(err);
|
||||
if (err.code === 'EEXIST') { // curDir already exists!
|
||||
return curDir;
|
||||
|
@ -57,8 +55,7 @@ function writeFileSync(path, buffer, permission) {
|
|||
let fileDescriptor;
|
||||
try {
|
||||
fileDescriptor = fs.openSync(path, 'w', permission);
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
fs.chmodSync(path, permission);
|
||||
fileDescriptor = fs.openSync(path, 'w', permission);
|
||||
}
|
||||
|
@ -104,8 +101,7 @@ async function updateTotalStorageUsed() {
|
|||
if (verifiedPath !== null) {
|
||||
try {
|
||||
totalStorageUsed = execSync(`du -hs ${verifiedPath} | awk -F'\t' '{print $1;}'`).toString();
|
||||
}
|
||||
catch (exception) {
|
||||
} catch (exception) {
|
||||
totalStorageUsed = 'Unsupported Platform';
|
||||
logger.debug('Unable to calculate storage used, only supported on systems with \'du\' available');
|
||||
}
|
||||
|
@ -129,6 +125,6 @@ module.exports = (_models, _logger) => {
|
|||
writeFileSync,
|
||||
moveUploadedFile,
|
||||
updateTotalStorageUsed,
|
||||
getTotalStorageUsed
|
||||
getTotalStorageUsed,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,4 +1 @@
|
|||
|
||||
|
||||
|
||||
function getUploadURL(driveType) {}
|
||||
function getUploadURL(driveType) {}
|
||||
|
|
|
@ -25,7 +25,7 @@ async function createAccount(email, password) {
|
|||
password,
|
||||
created: Date.now(),
|
||||
last_ping: Date.now(),
|
||||
email_verify_token: emailToken
|
||||
email_verify_token: emailToken,
|
||||
});
|
||||
|
||||
const didAccountRegister = await models_orm.models.accounts.findOne({ where: { email } });
|
||||
|
@ -38,7 +38,7 @@ async function createAccount(email, password) {
|
|||
async function verifyEmailToken(token) {
|
||||
if (!token) return { success: false, status: 400, data: { missingToken: true } };
|
||||
const account = await models_orm.models.accounts.findOne(
|
||||
{ where: { email_verify_token: token } }
|
||||
{ where: { email_verify_token: token } },
|
||||
);
|
||||
|
||||
if (account === null) return { success: false, status: 404, data: { badToken: true } };
|
||||
|
@ -48,13 +48,13 @@ async function verifyEmailToken(token) {
|
|||
|
||||
const update = models_orm.models.accounts.update(
|
||||
{
|
||||
verified: true
|
||||
verified: true,
|
||||
},
|
||||
{
|
||||
where: {
|
||||
id: account.id
|
||||
}
|
||||
}
|
||||
id: account.id,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
return { success: true, status: 200, data: { successfullyVerified: true } };
|
||||
|
@ -69,5 +69,5 @@ module.exports = {
|
|||
createAccount,
|
||||
verifyEmailToken,
|
||||
getAccountFromId,
|
||||
getAllUsers
|
||||
getAllUsers,
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
module.exports = {
|
||||
apps : [{
|
||||
name : "Retropilot Service",
|
||||
script : "./server.js",
|
||||
apps: [{
|
||||
name: 'Retropilot Service',
|
||||
script: './server.js',
|
||||
|
||||
env_development: {
|
||||
NODE_ENV: "development",
|
||||
}
|
||||
NODE_ENV: 'development',
|
||||
},
|
||||
}],
|
||||
}
|
||||
};
|
||||
|
|
|
@ -6,41 +6,41 @@ module.exports = (sequelize) => {
|
|||
allowNull: false,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
account_id: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
device_id: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
action: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
user_ip: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
device_ip: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
meta: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
created_at: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
dongle_id: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
}
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
}, {
|
||||
timestamps: false
|
||||
timestamps: false,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -6,34 +6,34 @@ module.exports = (sequelize) => {
|
|||
allowNull: false,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
device_id: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
type: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
data: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
created_at: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
uuid: {
|
||||
allowNull: false,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
resolved_at: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
}
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
|
||||
}, {
|
||||
timestamps: false
|
||||
timestamps: false,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -6,34 +6,34 @@ module.exports = (sequelize) => {
|
|||
allowNull: false,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
account_id: {
|
||||
allowNull: false,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
device_id: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
athena: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
unpair: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
view_drives: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
created_at: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
}
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
|
||||
}, {
|
||||
timestamps: false
|
||||
timestamps: false,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -14,6 +14,6 @@ module.exports = (_db) => {
|
|||
getAccountFromId,
|
||||
getAccountFromVerifyToken,
|
||||
verifyAccountEmail,
|
||||
banAccount
|
||||
banAccount,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,60 +8,60 @@ module.exports = (sequelize) => {
|
|||
allowNull: false,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
dongle_id: {
|
||||
allowNull: false,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
account_id: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
imei: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
serial: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
device_type: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
public_key: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
created: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
last_ping: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
storage_used: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
|
||||
max_storage: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
ignore_uploads: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
nickname: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
}
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: false
|
||||
}
|
||||
timestamps: false,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
|
||||
|
||||
|
||||
let db;
|
||||
|
||||
function getDrives(dongleId) {
|
||||
|
@ -8,21 +5,22 @@ function getDrives(dongleId) {
|
|||
}
|
||||
|
||||
async function getDevice(dongleId) {
|
||||
return await db.get('SELECT * FROM devices WHERE dongle_id = ?', dongleId);
|
||||
return await db.get('SELECT * FROM devices WHERE dongle_id = ?', dongleId);
|
||||
}
|
||||
|
||||
async function deviceCheckIn(dongleId) {
|
||||
return await db.run(
|
||||
'UPDATE devices SET last_ping = ? WHERE dongle_id = ?',
|
||||
Date.now(), dongleId
|
||||
);
|
||||
return await db.run(
|
||||
'UPDATE devices SET last_ping = ? WHERE dongle_id = ?',
|
||||
Date.now(),
|
||||
dongleId,
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = (_db) => {
|
||||
db = _db;
|
||||
db = _db;
|
||||
|
||||
return {
|
||||
getDevice,
|
||||
deviceCheckIn
|
||||
}
|
||||
}
|
||||
return {
|
||||
getDevice,
|
||||
deviceCheckIn,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,71 +8,71 @@ module.exports = (sequelize) => {
|
|||
allowNull: false,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
identifier: {
|
||||
allowNull: false,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
dongle_id: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
max_segment: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
upload_complete: {
|
||||
allowedNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
duration: {
|
||||
allowNull: true,
|
||||
type: DataTypes.NUMBER
|
||||
type: DataTypes.NUMBER,
|
||||
},
|
||||
distance_meters: {
|
||||
allowNull: true,
|
||||
type: DataTypes.NUMBER
|
||||
type: DataTypes.NUMBER,
|
||||
},
|
||||
filesize: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
is_processed: {
|
||||
allowNull: true,
|
||||
type: DataTypes.BOOLEAN
|
||||
type: DataTypes.BOOLEAN,
|
||||
},
|
||||
created: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
last_upload: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
is_preserved: {
|
||||
allowNull: true,
|
||||
type: DataTypes.BOOLEAN
|
||||
type: DataTypes.BOOLEAN,
|
||||
},
|
||||
is_deleted: {
|
||||
allowNull: true,
|
||||
type: DataTypes.BOOLEAN
|
||||
type: DataTypes.BOOLEAN,
|
||||
},
|
||||
drive_date: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
is_physically_removed: {
|
||||
allowNull: true,
|
||||
type: DataTypes.BOOLEAN
|
||||
type: DataTypes.BOOLEAN,
|
||||
},
|
||||
metadata: {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
}
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: false
|
||||
}
|
||||
timestamps: false,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,55 +1,49 @@
|
|||
const sqlite3 = require('sqlite3')
|
||||
const {open} = require('sqlite')
|
||||
const config = require('./../config');
|
||||
const sqlite3 = require('sqlite3');
|
||||
const { open } = require('sqlite');
|
||||
const config = require('../config');
|
||||
|
||||
async function validateDatabase(db, logger) {
|
||||
try {
|
||||
db = await open({
|
||||
filename: config.databaseFile,
|
||||
driver: sqlite3.Database,
|
||||
mode: sqlite3.OPEN_READWRITE
|
||||
});
|
||||
await db.get('SELECT * FROM accounts LIMIT 1')
|
||||
await db.get('SELECT * FROM devices LIMIT 1')
|
||||
await db.get('SELECT * FROM drives LIMIT 1')
|
||||
await db.get('SELECT * FROM drive_segments LIMIT 1')
|
||||
|
||||
} catch (exception) {
|
||||
logger.error(exception);
|
||||
process.exit();
|
||||
}
|
||||
try {
|
||||
db = await open({
|
||||
filename: config.databaseFile,
|
||||
driver: sqlite3.Database,
|
||||
mode: sqlite3.OPEN_READWRITE,
|
||||
});
|
||||
await db.get('SELECT * FROM accounts LIMIT 1');
|
||||
await db.get('SELECT * FROM devices LIMIT 1');
|
||||
await db.get('SELECT * FROM drives LIMIT 1');
|
||||
await db.get('SELECT * FROM drive_segments LIMIT 1');
|
||||
} catch (exception) {
|
||||
logger.error(exception);
|
||||
process.exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = async (logger) => {
|
||||
let db;
|
||||
let db;
|
||||
|
||||
try {
|
||||
db = await open({
|
||||
filename: config.databaseFile,
|
||||
driver: sqlite3.Database,
|
||||
mode: sqlite3.OPEN_READWRITE
|
||||
});
|
||||
try {
|
||||
db = await open({
|
||||
filename: config.databaseFile,
|
||||
driver: sqlite3.Database,
|
||||
mode: sqlite3.OPEN_READWRITE,
|
||||
});
|
||||
} catch (exception) {
|
||||
logger.error(exception);
|
||||
process.exit();
|
||||
}
|
||||
|
||||
} 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.
|
||||
|
||||
// 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);
|
||||
|
||||
await validateDatabase(db, logger);
|
||||
return {
|
||||
models: {
|
||||
drivesModel: require('./drives')(db),
|
||||
users: require('./users')(db),
|
||||
|
||||
|
||||
return {
|
||||
models: {
|
||||
drivesModel: require('./drives')(db),
|
||||
users: require('./users')(db),
|
||||
|
||||
// TODO remove access to DB queries from non models
|
||||
__db: db // to be removed when db queries are removed from outside models.
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO remove access to DB queries from non models
|
||||
__db: db, // to be removed when db queries are removed from outside models.
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@ const { Sequelize } = require('sequelize');
|
|||
|
||||
const sequelize = new Sequelize({
|
||||
dialect: 'sqlite',
|
||||
storage: 'database.sqlite'
|
||||
storage: 'database.sqlite',
|
||||
});
|
||||
|
||||
sequelize.options.logging = () => {};
|
||||
|
@ -16,7 +16,7 @@ const modelDefiners = [
|
|||
require('./users.model'),
|
||||
require('./athena_action_log.model'),
|
||||
require('./athena_returned_data.model'),
|
||||
require('./device_authorised_users.model')
|
||||
require('./device_authorised_users.model'),
|
||||
];
|
||||
|
||||
for (const modelDefiner of modelDefiners) {
|
||||
|
|
|
@ -1,45 +1,44 @@
|
|||
let db;
|
||||
|
||||
async function userPing(email) {
|
||||
return await db.run('UPDATE accounts SET last_ping = ? WHERE email = ?', Date.now(), 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);
|
||||
return await db.get('SELECT * FROM accounts WHERE LOWER(email) = ?', email);
|
||||
}
|
||||
|
||||
async function getAccountFromVerifyToken(token) {
|
||||
return await db.get('SELECT * FROM accounts WHERE email_verify_token = ?', token);
|
||||
return await db.get('SELECT * FROM accounts WHERE email_verify_token = ?', token);
|
||||
}
|
||||
|
||||
async function getAccountFromId(id) {
|
||||
return await db.get('SELECT * FROM accounts WHERE id = ?', id);
|
||||
return await db.get('SELECT * FROM accounts WHERE id = ?', id);
|
||||
}
|
||||
|
||||
async function createUser(email, password, created, lastPing, emailToken) {
|
||||
return await db.get('INSERT INTO accounts (email, password, created, last_ping, email_verify_token) VALUES (?,?,?,?,?)', email, password, created, lastPing, emailToken)
|
||||
return await db.get('INSERT INTO accounts (email, password, created, last_ping, email_verify_token) VALUES (?,?,?,?,?)', email, password, created, lastPing, emailToken);
|
||||
}
|
||||
|
||||
async function verifyAccountEmail(email, verified, newToken) {
|
||||
verified = verified === true ? 1 : 0
|
||||
return await db.get('UPDATE accounts SET verified=? WHERE email = ?', verified, email);
|
||||
verified = verified === true ? 1 : 0;
|
||||
return await db.get('UPDATE accounts SET verified=? WHERE email = ?', verified, email);
|
||||
}
|
||||
|
||||
async function banAccount(ban, userId) {
|
||||
return await db.get('UPDATE accounts SET banned=? WHERE id = ?', ban ? 1 : 0, userId)
|
||||
return await db.get('UPDATE accounts SET banned=? WHERE id = ?', ban ? 1 : 0, userId);
|
||||
}
|
||||
|
||||
|
||||
module.exports = (_db) => {
|
||||
db = _db;
|
||||
db = _db;
|
||||
|
||||
return {
|
||||
userPing,
|
||||
getAccountFromEmail,
|
||||
createUser,
|
||||
getAccountFromId,
|
||||
getAccountFromVerifyToken,
|
||||
verifyAccountEmail,
|
||||
banAccount
|
||||
}
|
||||
}
|
||||
return {
|
||||
userPing,
|
||||
getAccountFromEmail,
|
||||
createUser,
|
||||
getAccountFromId,
|
||||
getAccountFromVerifyToken,
|
||||
verifyAccountEmail,
|
||||
banAccount,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -6,33 +6,33 @@ module.exports = (sequelize) => {
|
|||
allowNull: false,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
email: {
|
||||
allowNull: false,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
password: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
created: {
|
||||
allowNull: true,
|
||||
type: DataTypes.NUMBER
|
||||
type: DataTypes.NUMBER,
|
||||
},
|
||||
last_ping: {
|
||||
allowNull: true,
|
||||
type: DataTypes.NUMBER
|
||||
type: DataTypes.NUMBER,
|
||||
},
|
||||
'2fa_token': {
|
||||
allowNull: true,
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
admin: {
|
||||
allowNull: true,
|
||||
type: DataTypes.INTEGER
|
||||
}
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
}, {
|
||||
timestamps: false
|
||||
timestamps: false,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -2,128 +2,108 @@ const router = require('express').Router();
|
|||
const bodyParser = require('body-parser');
|
||||
const crypto = require('crypto');
|
||||
const { route } = require('../../server');
|
||||
const config = require('./../../config');
|
||||
const deviceController = require('./../../controllers/devices')
|
||||
const config = require('../../config');
|
||||
const deviceController = require('../../controllers/devices');
|
||||
|
||||
function runAsyncWrapper(callback) {
|
||||
return function (req, res, next) {
|
||||
callback(req, res, next)
|
||||
.catch(next)
|
||||
}
|
||||
return function (req, res, next) {
|
||||
callback(req, res, next)
|
||||
.catch(next);
|
||||
};
|
||||
}
|
||||
|
||||
let models;
|
||||
let controllers;
|
||||
let logger;
|
||||
|
||||
|
||||
|
||||
// probs should put middleware somewhere else
|
||||
router.use(async function (req, res, next) {
|
||||
const currentAdmin = await controllers.admin.isCurrentUserAdmin(true, req);
|
||||
if (currentAdmin.isAdmin === false) {
|
||||
return res.status(402).json({error:true, msg: 'NOT AUTHORISED', status: 403}).end();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
router.use(async (req, res, next) => {
|
||||
const currentAdmin = await controllers.admin.isCurrentUserAdmin(true, req);
|
||||
if (currentAdmin.isAdmin === false) {
|
||||
return res.status(402).json({ error: true, msg: 'NOT AUTHORISED', status: 403 }).end();
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
|
||||
// TODO
|
||||
|
||||
// TODO
|
||||
|
||||
router.get('/user/:userId/ban/:ban', runAsyncWrapper(async (req, res) => {
|
||||
const banResult = await controllers.admin.banAccount(req.params.ban, req.params.userId)
|
||||
if (banResult.hasOwnProperty('success') && banResult.success === true) {
|
||||
res.status(200).json(banResult);
|
||||
} else {
|
||||
res.status(500).json(banResult)
|
||||
}
|
||||
|
||||
const banResult = await controllers.admin.banAccount(req.params.ban, req.params.userId);
|
||||
if (banResult.hasOwnProperty('success') && banResult.success === true) {
|
||||
res.status(200).json(banResult);
|
||||
} else {
|
||||
res.status(500).json(banResult);
|
||||
}
|
||||
}));
|
||||
|
||||
router.get('/user/:userId/get/devices', runAsyncWrapper(async (req, res) => {
|
||||
if (!req.params.userId) { return req.status(400).json({error: true, msg: 'MISSING DATA', status: 400})}
|
||||
if (!req.params.userId) { return req.status(400).json({ error: true, msg: 'MISSING DATA', status: 400 }); }
|
||||
|
||||
return res.status(200).json({success: true, data: controllers.devices.getDevices(req.params.userId)})
|
||||
return res.status(200).json({ success: true, data: controllers.devices.getDevices(req.params.userId) });
|
||||
}));
|
||||
|
||||
|
||||
|
||||
router.get('/user/', runAsyncWrapper(async (req, res) => {
|
||||
console.warn("PROCESSED")
|
||||
|
||||
|
||||
return res.status(200).json({success: true, data: await controllers.users.getAllUsers()})
|
||||
console.warn('PROCESSED');
|
||||
|
||||
return res.status(200).json({ success: true, data: await controllers.users.getAllUsers() });
|
||||
}));
|
||||
|
||||
router.get('/device/:dongle_id', runAsyncWrapper(async (req, res) => {
|
||||
if (!req.params.dongle_id) { return req.status(400).json({error: true, msg: 'MISSING DATA', status: 400})}
|
||||
|
||||
|
||||
return res.status(200).json({success: true, data: await controllers.devices.getDeviceFromDongle(getDeviceFromDongle)})
|
||||
if (!req.params.dongle_id) { return req.status(400).json({ error: true, msg: 'MISSING DATA', status: 400 }); }
|
||||
|
||||
return res.status(200).json({ success: true, data: await controllers.devices.getDeviceFromDongle(getDeviceFromDongle) });
|
||||
}));
|
||||
|
||||
router.get('/device/:dongle_id/pair/:user_id', runAsyncWrapper(async (req, res) => {
|
||||
if (!req.params.dongle_id || !req.params.user_id) { return req.status(400).json({error: true, msg: 'MISSING DATA', status: 400})}
|
||||
|
||||
const pairDeviceToAccountId = await controllers.devices.pairDeviceToAccountId(req.params.dongle_id, req.params.user_id)
|
||||
if (!req.params.dongle_id || !req.params.user_id) { return req.status(400).json({ error: true, msg: 'MISSING DATA', status: 400 }); }
|
||||
|
||||
return res.status(200).json(pairDeviceToAccountId)
|
||||
const pairDeviceToAccountId = await controllers.devices.pairDeviceToAccountId(req.params.dongle_id, req.params.user_id);
|
||||
|
||||
return res.status(200).json(pairDeviceToAccountId);
|
||||
}));
|
||||
|
||||
router.get('/device', runAsyncWrapper(async (req, res) => {
|
||||
const filteredDevices = await controllers.devices.getAllDevicesFiltered();
|
||||
console.log("fil", filteredDevices)
|
||||
return res.status(200).json({success: true, data: filteredDevices})
|
||||
|
||||
const filteredDevices = await controllers.devices.getAllDevicesFiltered();
|
||||
console.log('fil', filteredDevices);
|
||||
return res.status(200).json({ success: true, data: filteredDevices });
|
||||
}));
|
||||
|
||||
router.get('/device/:dongle_id/ignore/:ignore_uploads', runAsyncWrapper(async (req, res) => {
|
||||
if (!req.params.dongle_id || !req.params.ignore_uploads) { return req.status(400).json({error: true, msg: 'MISSING DATA', status: 400})}
|
||||
|
||||
if (!req.params.dongle_id || !req.params.ignore_uploads) { return req.status(400).json({ error: true, msg: 'MISSING DATA', status: 400 }); }
|
||||
}));
|
||||
|
||||
router.get('/admin/device/:dongle_id/ignore/:ignore_uploads', runAsyncWrapper(async (req, res) => {
|
||||
if (!req.params.dongle_id || !req.params.ignore_uploads) { return req.status(400).json({error: true, msg: 'MISSING DATA', status: 400})}
|
||||
if (!req.params.dongle_id || !req.params.ignore_uploads) { return req.status(400).json({ error: true, msg: 'MISSING DATA', status: 400 }); }
|
||||
|
||||
let ignore = null;
|
||||
let ignore = null;
|
||||
|
||||
switch (req.params.ignore_uploads) {
|
||||
case "true":
|
||||
ignore = true
|
||||
break;
|
||||
case "false":
|
||||
ignore = false
|
||||
break;
|
||||
default:
|
||||
return res.json({error: true, msg: 'MISSING DATA'})
|
||||
break
|
||||
}
|
||||
switch (req.params.ignore_uploads) {
|
||||
case 'true':
|
||||
ignore = true;
|
||||
break;
|
||||
case 'false':
|
||||
ignore = false;
|
||||
break;
|
||||
default:
|
||||
return res.json({ error: true, msg: 'MISSING DATA' });
|
||||
break;
|
||||
}
|
||||
|
||||
if (ignore === null) {return}
|
||||
|
||||
await controllers.devices.setIgnoredUploads(req.params.dongle_id);
|
||||
return res.status(200).json({success: true});
|
||||
if (ignore === null) { return; }
|
||||
|
||||
await controllers.devices.setIgnoredUploads(req.params.dongle_id);
|
||||
return res.status(200).json({ success: true });
|
||||
}));
|
||||
|
||||
|
||||
router.get('/device/:dongle_id/athena/reboot', runAsyncWrapper(async (req, res) => {
|
||||
|
||||
req.athenaWebsocketTemp.rebootDevice(req.params.dongle_id)
|
||||
res.send("ok");
|
||||
|
||||
req.athenaWebsocketTemp.rebootDevice(req.params.dongle_id);
|
||||
res.send('ok');
|
||||
}));
|
||||
|
||||
|
||||
module.exports = (_models, _controllers, _logger) => {
|
||||
models = _models;
|
||||
controllers = _controllers;
|
||||
logger = _logger;
|
||||
models = _models;
|
||||
controllers = _controllers;
|
||||
logger = _logger;
|
||||
|
||||
return router;
|
||||
}
|
||||
return router;
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@ let logger;
|
|||
router.put('/backend/post_upload', bodyParser.raw({
|
||||
inflate: true,
|
||||
limit: '100000kb',
|
||||
type: '*/*'
|
||||
type: '*/*',
|
||||
}), runAsyncWrapper(async (req, res) => {
|
||||
// TODO update buffer functions project wide
|
||||
var buf = new Buffer(req.body.toString('binary'), 'binary');
|
||||
|
@ -38,23 +38,20 @@ router.put('/backend/post_upload', bodyParser.raw({
|
|||
logger.error(`HTTP.PUT /backend/post_upload token mismatch (${token} vs ${req.query.token})`);
|
||||
res.status(400);
|
||||
res.send('Malformed request');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
logger.info('HTTP.PUT /backend/post_upload permissions checked, calling moveUploadedFile');
|
||||
const moveResult = controllers.storage.moveUploadedFile(buf, directory, filename);
|
||||
if (moveResult === false) {
|
||||
logger.error('HTTP.PUT /backend/post_upload moveUploadedFile failed');
|
||||
res.status(500);
|
||||
res.send('Internal Server Error');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
logger.info(`HTTP.PUT /backend/post_upload succesfully uploaded to ${moveResult}`);
|
||||
res.status(200);
|
||||
res.json(['OK']);
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // boot or crash upload
|
||||
} else { // boot or crash upload
|
||||
var filename = req.query.file;
|
||||
var directory = req.query.dir;
|
||||
var token = crypto.createHmac('sha256', config.applicationSalt).update(dongleId + filename + directory + ts).digest('hex');
|
||||
|
@ -64,16 +61,14 @@ router.put('/backend/post_upload', bodyParser.raw({
|
|||
logger.error(`HTTP.PUT /backend/post_upload token mismatch (${token} vs ${req.query.token})`);
|
||||
res.status(400);
|
||||
res.send('Malformed request');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
logger.info('HTTP.PUT /backend/post_upload permissions checked, calling moveUploadedFile');
|
||||
var moveResult = controllers.storage.moveUploadedFile(buf, directory, filename);
|
||||
if (moveResult === false) {
|
||||
logger.error('HTTP.PUT /backend/post_upload moveUploadedFile failed');
|
||||
res.status(500);
|
||||
res.send('Internal Server Error');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
logger.info(`HTTP.PUT /backend/post_upload succesfully uploaded to ${moveResult}`);
|
||||
res.status(200);
|
||||
res.json(['OK']);
|
||||
|
@ -120,13 +115,13 @@ router.get('/v1.1/devices/:dongleId/stats', runAsyncWrapper(async (req, res) =>
|
|||
all: {
|
||||
routes: 0,
|
||||
distance: 0,
|
||||
minutes: 0
|
||||
minutes: 0,
|
||||
},
|
||||
week: {
|
||||
routes: 0,
|
||||
distance: 0,
|
||||
minutes: 0
|
||||
}
|
||||
minutes: 0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
@ -259,8 +254,7 @@ async function upload(req, res) {
|
|||
|
||||
responseUrl = `${config.baseUploadUrl}?file=${filename}&dir=${directory}&dongleId=${dongleId}&ts=${ts}&token=${token}`;
|
||||
logger.info(`HTTP.UPLOAD_URL matched '${uploadType}' file upload, constructed responseUrl: ${responseUrl}`);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// "2021-04-12--01-44-25--0/qlog.bz2" for example
|
||||
const subdirPosition = path.split('--', 2).join('--').length;
|
||||
const filenamePosition = path.indexOf('/');
|
||||
|
@ -325,7 +319,7 @@ async function upload(req, res) {
|
|||
|
||||
false,
|
||||
|
||||
false
|
||||
false,
|
||||
);
|
||||
|
||||
const driveSegmentResult = await models.__db.run(
|
||||
|
@ -346,12 +340,11 @@ async function upload(req, res) {
|
|||
|
||||
false,
|
||||
|
||||
Date.now()
|
||||
Date.now(),
|
||||
);
|
||||
|
||||
logger.info(`HTTP.UPLOAD_URL created new drive #${JSON.stringify(driveResult.lastID)}`);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const driveResult = await models.__db.run(
|
||||
'UPDATE drives SET last_upload = ?, max_segment = ?, upload_complete = ?, is_processed = ? WHERE identifier = ? AND dongle_id = ?',
|
||||
Date.now(),
|
||||
|
@ -364,7 +357,7 @@ async function upload(req, res) {
|
|||
|
||||
driveName,
|
||||
|
||||
dongleId
|
||||
dongleId,
|
||||
);
|
||||
|
||||
const drive_segment = await models.__db.get('SELECT * FROM drive_segments WHERE drive_identifier = ? AND dongle_id = ? AND segment_id = ?', driveName, dongleId, segment);
|
||||
|
@ -388,10 +381,9 @@ async function upload(req, res) {
|
|||
|
||||
false,
|
||||
|
||||
Date.now()
|
||||
Date.now(),
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const driveSegmentResult = await models.__db.run(
|
||||
'UPDATE drive_segments SET upload_complete = ?, is_stalled = ? WHERE drive_identifier = ? AND dongle_id = ? AND segment_id = ?',
|
||||
false,
|
||||
|
@ -402,7 +394,7 @@ async function upload(req, res) {
|
|||
|
||||
dongleId,
|
||||
|
||||
segment
|
||||
segment,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -414,8 +406,7 @@ async function upload(req, res) {
|
|||
if (responseUrl != null) {
|
||||
res.status(200);
|
||||
res.json({ url: responseUrl, headers: { 'Content-Type': 'application/octet-stream' } });
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
logger.error('HTTP.UPLOAD_URL unable to match request, responding with HTTP 400');
|
||||
res.status(400);
|
||||
res.send('Malformed Request.');
|
||||
|
@ -473,7 +464,7 @@ router.post('/v2/pilotauth/', bodyParser.urlencoded({ extended: true }), async (
|
|||
|
||||
Date.now(),
|
||||
|
||||
0
|
||||
0,
|
||||
);
|
||||
|
||||
const device = await models.__db.get('SELECT * FROM devices WHERE dongle_id = ?', dongleId);
|
||||
|
@ -484,15 +475,14 @@ router.post('/v2/pilotauth/', bodyParser.urlencoded({ extended: true }), async (
|
|||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const result = await models.__db.run(
|
||||
'UPDATE devices SET last_ping = ?, public_key = ? WHERE dongle_id = ?',
|
||||
Date.now(),
|
||||
|
||||
public_key,
|
||||
|
||||
device.dongle_id
|
||||
device.dongle_id,
|
||||
);
|
||||
|
||||
logger.info(`HTTP.V2.PILOTAUTH REACTIVATING KNOWN DEVICE (${imei1}, ${serial}) with dongle_id ${device.dongle_id}`);
|
||||
|
@ -545,7 +535,7 @@ router.get('/useradmin/cabana_drive/:extendedRouteIdentifier', runAsyncWrapper(a
|
|||
driveUrl,
|
||||
name: `${drive.dongle_id}|${drive.identifier}`,
|
||||
driveIdentifier: drive.identifier,
|
||||
dongleId: drive.dongle_id
|
||||
dongleId: drive.dongle_id,
|
||||
});
|
||||
}));
|
||||
|
||||
|
|
|
@ -12,11 +12,10 @@ async function isAuthenticated(req, res, next) {
|
|||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
authenticated: false
|
||||
}
|
||||
authenticated: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
req.account = account;
|
||||
next();
|
||||
}
|
||||
|
@ -30,16 +29,16 @@ router.get('/retropilot/0/useradmin/session', isAuthenticated, async (req, res)
|
|||
success: true,
|
||||
data: {
|
||||
authenticated: true,
|
||||
user: account.dataValues
|
||||
}
|
||||
user: account.dataValues,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
data: {
|
||||
authenticated: false
|
||||
}
|
||||
authenticated: false,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -56,16 +55,15 @@ router.post('/retropilot/0/useradmin/auth', bodyParser.urlencoded({ extended: tr
|
|||
data: {
|
||||
authenticated: true,
|
||||
jwt: signIn.jwt,
|
||||
user: account.dataValues
|
||||
}
|
||||
user: account.dataValues,
|
||||
},
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
authenticated: false
|
||||
}
|
||||
authenticated: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -80,8 +78,7 @@ router.get('/session/get', async (req, res) => {
|
|||
|
||||
if (!account) {
|
||||
res.json({ success: true, hasSession: false, session: {} });
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res.json({ success: true, hasSession: false, session: account });
|
||||
}
|
||||
});
|
||||
|
|
|
@ -12,8 +12,7 @@ async function isAuthenticated(req, res, next) {
|
|||
|
||||
if (account === null) {
|
||||
res.json({ success: false, msg: 'NOT_AUTHENTICATED1' });
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
req.account = account;
|
||||
next();
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ const whitelistParams = {
|
|||
getsiminfo: true,
|
||||
getnetworktype: true,
|
||||
getnetworks: true,
|
||||
takesnapshot: true
|
||||
takesnapshot: true,
|
||||
};
|
||||
|
||||
router.get('/dongle/:dongle_id/connected', async (req, res) => {
|
||||
|
@ -42,7 +42,7 @@ router.get('/dongle/:dongle_id/connected', async (req, res) => {
|
|||
const deviceConnected = await req.athenaWebsocketTemp.isDeviceConnected(device.id, account.id, device.dongle_id);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true, dongle_id: device.dongle_id, data: deviceConnected
|
||||
success: true, dongle_id: device.dongle_id, data: deviceConnected,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -69,7 +69,7 @@ router.get('/dongle/:dongle_id/send/:method/', async (req, res) => {
|
|||
const data = await req.athenaWebsocketTemp.invoke(req.params.method, null, device.dongle_id, account.id);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true, dongle_id: device.dongle_id, method: req.params.method, data
|
||||
success: true, dongle_id: device.dongle_id, method: req.params.method, data,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -108,7 +108,7 @@ router.get('/dongle/:dongle_id/temp/nav/:lat/:long', async (req, res) => {
|
|||
const data = await req.athenaWebsocketTemp.invoke('setNavDestination', { latitude: req.params.lat, longitude: req.params.long }, device.dongle_id, account.id);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true, dongle_id: device.dongle_id, method: req.params.method, data
|
||||
success: true, dongle_id: device.dongle_id, method: req.params.method, data,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -7,5 +7,5 @@ module.exports = (_models, _controllers, _logger) => ({
|
|||
realtime: require('./api/realtime'),
|
||||
|
||||
deviceApi: require('./api/devices'),
|
||||
authenticationApi: require('./api/authentication')
|
||||
authenticationApi: require('./api/authentication'),
|
||||
});
|
||||
|
|
|
@ -24,8 +24,7 @@ router.post('/retropilot/0/useradmin/auth', bodyParser.urlencoded({ extended: tr
|
|||
if (signIn.success) {
|
||||
res.cookie('jwt', signIn.jwt);
|
||||
res.redirect('/useradmin/overview');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res.redirect(`/useradmin?status=${encodeURIComponent('Invalid credentials or banned account')}`);
|
||||
}
|
||||
}));
|
||||
|
@ -46,14 +45,14 @@ router.get('/retropilot/0/useradmin', runAsyncWrapper(async (req, res) => {
|
|||
serverStats: {
|
||||
config: {
|
||||
registerAllowed: config.allowAccountRegistration,
|
||||
welcomeMessage: config.welcomeMessage
|
||||
welcomeMessage: config.welcomeMessage,
|
||||
},
|
||||
accounts: accounts.num,
|
||||
devices: devices.num,
|
||||
drives: drives.num,
|
||||
storageUsed: await controllers.storage.getTotalStorageUsed()
|
||||
}
|
||||
}
|
||||
storageUsed: await controllers.storage.getTotalStorageUsed(),
|
||||
},
|
||||
},
|
||||
}).status(200);
|
||||
}));
|
||||
|
||||
|
@ -178,8 +177,8 @@ router.get('/retropilot/0/overview', runAsyncWrapper(async (req, res) => {
|
|||
success: true,
|
||||
data: {
|
||||
account,
|
||||
devices
|
||||
}
|
||||
devices,
|
||||
},
|
||||
|
||||
}).status(200);
|
||||
}));
|
||||
|
@ -199,7 +198,7 @@ router.get('/retropilot/0/unpair_device/:dongleId', runAsyncWrapper(async (req,
|
|||
const result = await models.__db.run(
|
||||
'UPDATE devices SET account_id = ? WHERE dongle_id = ?',
|
||||
0,
|
||||
req.params.dongleId
|
||||
req.params.dongleId,
|
||||
);
|
||||
|
||||
res.json({ success: true, data: { unlink: true } });
|
||||
|
@ -215,10 +214,9 @@ router.post('/retropilot/0/pair_device', bodyParser.urlencoded({ extended: true
|
|||
|
||||
if (pairDevice.success === true) {
|
||||
res.json({
|
||||
success: true, msg: 'Paired', status: 200, data: pairDevice
|
||||
success: true, msg: 'Paired', status: 200, data: pairDevice,
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res.json({ success: false, msg: 'error', data: pairDevice });
|
||||
}
|
||||
}));
|
||||
|
@ -233,8 +231,7 @@ router.post('/retropilot/0/password/change', bodyParser.urlencoded({ extended: t
|
|||
|
||||
if (pwChange.success === true) {
|
||||
res.json({ success: true });
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res.json({ success: false, data: pwChange });
|
||||
}
|
||||
}));
|
||||
|
|
235
server.js
235
server.js
|
@ -6,165 +6,134 @@ const http = require('http');
|
|||
const https = require('https');
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const rateLimit = require("express-rate-limit");
|
||||
const rateLimit = require('express-rate-limit');
|
||||
|
||||
log4js.configure({
|
||||
appenders: {logfile: {type: "file", filename: "server.log"}, out: {type: 'console'} /*{type: "file", filename: "server1.log"}*/},
|
||||
categories: {default: {appenders: ['out', 'logfile'], level: 'info'}},
|
||||
appenders: { logfile: { type: 'file', filename: 'server.log' }, out: { type: 'console' } /* {type: "file", filename: "server1.log"} */ },
|
||||
categories: { default: { appenders: ['out', 'logfile'], level: 'info' } },
|
||||
|
||||
});
|
||||
|
||||
|
||||
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_sqli = require('./models/index.model');
|
||||
let controllers = require('./controllers');
|
||||
let routers = require('./routes')
|
||||
const athena = require('./websocket/athena');
|
||||
const webWebsocket = require('./websocket/web');
|
||||
var cookieParser = require('cookie-parser');
|
||||
const webWebsocket = require('./websocket/web');
|
||||
const athena = require('./websocket/athena');
|
||||
let routers = require('./routes');
|
||||
const models_sqli = require('./models/index.model');
|
||||
let controllers = require('./controllers');
|
||||
let models = require('./models/index');
|
||||
const router = require('./routes/api/realtime');
|
||||
|
||||
|
||||
|
||||
let db;
|
||||
|
||||
|
||||
// TODO
|
||||
function runAsyncWrapper(callback) {
|
||||
return function (req, res, next) {
|
||||
callback(req, res, next)
|
||||
.catch(next)
|
||||
}
|
||||
return function (req, res, next) {
|
||||
callback(req, res, next)
|
||||
.catch(next);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const app = express();
|
||||
|
||||
|
||||
const athenaRateLimit = rateLimit({
|
||||
windowMs: 30000,
|
||||
max: config.athena.api.ratelimit
|
||||
windowMs: 30000,
|
||||
max: config.athena.api.ratelimit,
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const web = async () => {
|
||||
// TODO clean up
|
||||
const _models = await models(logger);
|
||||
db = _models.models.__db;
|
||||
models = _models.models;
|
||||
// TODO clean up
|
||||
const _models = await models(logger);
|
||||
db = _models.models.__db;
|
||||
models = _models.models;
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
res.header('Access-Control-Allow-Origin', "http://localhost:3000");
|
||||
res.header('Access-Control-Allow-Credentials', true);
|
||||
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
|
||||
next();
|
||||
app.use((req, res, next) => {
|
||||
res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
|
||||
res.header('Access-Control-Allow-Credentials', true);
|
||||
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
|
||||
next();
|
||||
});
|
||||
|
||||
const _controllers = await controllers(models, logger);
|
||||
controllers = _controllers;
|
||||
|
||||
controllers.storage.initializeStorage();
|
||||
await controllers.storage.updateTotalStorageUsed();
|
||||
|
||||
routers = routers(models, controllers, logger);
|
||||
app.use(routers.api);
|
||||
app.use(routers.useradmin);
|
||||
app.use(routers.authenticationApi);
|
||||
|
||||
if (config.athena.enabled) {
|
||||
app.use((req, res, next) => {
|
||||
req.athenaWebsocketTemp = athena;
|
||||
return next();
|
||||
});
|
||||
|
||||
app.use('/admin', routers.admin);
|
||||
app.use('/realtime', athenaRateLimit);
|
||||
app.use('/realtime', routers.realtime);
|
||||
} else {
|
||||
logger.log('Athena disabled');
|
||||
}
|
||||
|
||||
app.use(cors({ origin: 'http://localhost:3000' }));
|
||||
app.use(cookieParser());
|
||||
app.use('/favicon.ico', express.static('static/favicon.ico'));
|
||||
app.use(config.baseDriveDownloadPathMapping, express.static(config.storagePath));
|
||||
|
||||
app.use(routers.deviceApi);
|
||||
|
||||
app.use('/.well-known', express.static('.well-known'));
|
||||
|
||||
app.use('/cabana', express.static('cabana/'));
|
||||
|
||||
app.get('/', async (req, res) => {
|
||||
res.status(200);
|
||||
var response = '<html style="font-family: monospace"><h2>404 Not found</h2>'
|
||||
+ 'Are you looking for the <a href="/useradmin">useradmin dashboard</a>?';
|
||||
res.send(response);
|
||||
});
|
||||
|
||||
app.get('*', runAsyncWrapper(async (req, res) => {
|
||||
logger.error(`HTTP.GET unhandled request: ${controllers.helpers.simpleStringify(req)}, ${controllers.helpers.simpleStringify(res)}`);
|
||||
res.status(404);
|
||||
res.send('Not Implemented');
|
||||
}));
|
||||
|
||||
app.post('*', runAsyncWrapper(async (req, res) => {
|
||||
logger.error(`HTTP.POST unhandled request: ${controllers.helpers.simpleStringify(req)}, ${controllers.helpers.simpleStringify(res)}`);
|
||||
res.status(404);
|
||||
res.send('Not Implemented');
|
||||
}));
|
||||
};
|
||||
|
||||
lockfile.lock('retropilot_server.lock', { realpath: false, stale: 30000, update: 2000 })
|
||||
.then((release) => {
|
||||
console.log('STARTING SERVER...');
|
||||
web();
|
||||
(async () => {
|
||||
var privateKey = fs.readFileSync(config.sslKey, 'utf8');
|
||||
var certificate = fs.readFileSync(config.sslCrt, 'utf8');
|
||||
var sslCredentials = { key: privateKey, cert: certificate/* , ca: fs.readFileSync('certs/ca.crt') */ };
|
||||
|
||||
var httpServer = http.createServer(app);
|
||||
var httpsServer = https.createServer(sslCredentials, app);
|
||||
|
||||
httpServer.listen(config.httpPort, config.httpInterface, () => {
|
||||
logger.info(`Retropilot Server listening at http://${config.httpInterface}:${config.httpPort}`);
|
||||
});
|
||||
|
||||
const _controllers = await controllers(models, logger);
|
||||
controllers = _controllers;
|
||||
|
||||
|
||||
controllers.storage.initializeStorage();
|
||||
await controllers.storage.updateTotalStorageUsed();
|
||||
|
||||
routers = routers(models, controllers, logger)
|
||||
app.use(routers.api);
|
||||
app.use(routers.useradmin);
|
||||
app.use(routers.authenticationApi)
|
||||
|
||||
if (config.athena.enabled) {
|
||||
app.use((req, res, next) => {
|
||||
req.athenaWebsocketTemp = athena;
|
||||
return next();
|
||||
});
|
||||
|
||||
|
||||
app.use('/admin', routers.admin);
|
||||
app.use('/realtime', athenaRateLimit);
|
||||
app.use('/realtime', routers.realtime);
|
||||
} else {
|
||||
logger.log("Athena disabled");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
app.use(cors({origin: 'http://localhost:3000',}));
|
||||
app.use(cookieParser());
|
||||
app.use('/favicon.ico', express.static('static/favicon.ico'));
|
||||
app.use(config.baseDriveDownloadPathMapping, express.static(config.storagePath));
|
||||
|
||||
app.use(routers.deviceApi)
|
||||
|
||||
app.use('/.well-known', express.static('.well-known'));
|
||||
|
||||
app.use('/cabana', express.static('cabana/'));
|
||||
|
||||
|
||||
app.get('/', async (req, res) => {
|
||||
res.status(200);
|
||||
var response = '<html style="font-family: monospace"><h2>404 Not found</h2>' +
|
||||
'Are you looking for the <a href="/useradmin">useradmin dashboard</a>?';
|
||||
res.send(response);
|
||||
})
|
||||
|
||||
|
||||
app.get('*', runAsyncWrapper(async (req, res) => {
|
||||
logger.error("HTTP.GET unhandled request: " + controllers.helpers.simpleStringify(req) + ", " + controllers.helpers.simpleStringify(res) + "")
|
||||
res.status(404);
|
||||
res.send('Not Implemented');
|
||||
}))
|
||||
|
||||
|
||||
app.post('*', runAsyncWrapper(async (req, res) => {
|
||||
logger.error("HTTP.POST unhandled request: " + controllers.helpers.simpleStringify(req) + ", " + controllers.helpers.simpleStringify(res) + "")
|
||||
res.status(404);
|
||||
res.send('Not Implemented');
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
|
||||
lockfile.lock('retropilot_server.lock', {realpath: false, stale: 30000, update: 2000})
|
||||
.then((release) => {
|
||||
console.log("STARTING SERVER...");
|
||||
web();
|
||||
(async () => {
|
||||
|
||||
|
||||
var privateKey = fs.readFileSync(config.sslKey, 'utf8');
|
||||
var certificate = fs.readFileSync(config.sslCrt, 'utf8');
|
||||
var sslCredentials = {key: privateKey, cert: certificate/* , ca: fs.readFileSync('certs/ca.crt') */};
|
||||
|
||||
var httpServer = http.createServer(app);
|
||||
var httpsServer = https.createServer(sslCredentials, app);
|
||||
|
||||
|
||||
httpServer.listen(config.httpPort, config.httpInterface, () => {
|
||||
logger.info(`Retropilot Server listening at http://${config.httpInterface}:${config.httpPort}`)
|
||||
});
|
||||
httpsServer.listen(config.httpsPort, config.httpsInterface, () => {
|
||||
logger.info(`Retropilot Server listening at https://${config.httpsInterface}:${config.httpsPort}`)
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
}).catch((e) => {
|
||||
console.error(e)
|
||||
httpsServer.listen(config.httpsPort, config.httpsInterface, () => {
|
||||
logger.info(`Retropilot Server listening at https://${config.httpsInterface}:${config.httpsPort}`);
|
||||
});
|
||||
})();
|
||||
}).catch((e) => {
|
||||
console.error(e);
|
||||
process.exit();
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
|
|
|
@ -25,8 +25,7 @@ function invoke(command, params, dongleId, accountId, id) {
|
|||
|
||||
if (!id) {
|
||||
uniqueID = uuid();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
uniqueID = id;
|
||||
}
|
||||
|
||||
|
@ -36,7 +35,7 @@ function invoke(command, params, dongleId, accountId, id) {
|
|||
device_id: websocket.device_id,
|
||||
type: command,
|
||||
created_at: Date.now(),
|
||||
uuid: uniqueID
|
||||
uuid: uniqueID,
|
||||
});
|
||||
|
||||
websocket.send(JSON.stringify(wss.retropilotFunc.commandBuilder(command, params, uniqueID)));
|
||||
|
@ -65,6 +64,6 @@ module.exports = (websocketServer) => {
|
|||
invoke,
|
||||
incoming,
|
||||
deviceStatus,
|
||||
realtimeCallback
|
||||
realtimeCallback,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -22,10 +22,9 @@ function __server() {
|
|||
if (config.athena.secure) {
|
||||
server = httpsServer.createServer({
|
||||
cert: readFileSync(config.sslCrt),
|
||||
key: readFileSync(config.sslKey)
|
||||
key: readFileSync(config.sslKey),
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
server = httpServer.createServer();
|
||||
}
|
||||
|
||||
|
@ -91,7 +90,7 @@ async function manageConnection(ws, res) {
|
|||
|
||||
console.log(await models.models.athena_returned_data.update({
|
||||
data: JSON.stringify(json),
|
||||
resolved_at: Date.now()
|
||||
resolved_at: Date.now(),
|
||||
}, { where: { device_id: ws.device_id, uuid: json.id } }));
|
||||
|
||||
wss.retropilotFunc.actionLogger(null, null, 'ATHENA_DEVICE_MESSAGE_UNKNOWN', null, ws._socket.remoteAddress, JSON.stringify([message]), ws.dongleId);
|
||||
|
@ -126,8 +125,7 @@ wss.retropilotFunc = {
|
|||
authenticateDongle: async (ws, res, cookies) => {
|
||||
try {
|
||||
unsafeJwt = jsonwebtoken.decode(cookies.jwt);
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
logger.info(`Athena(Websocket) - AUTHENTICATION FAILED (INVALID JWT) IP: ${ws._socket.remoteAddress}`);
|
||||
wss.retropilotFunc.actionLogger(null, null, 'ATHENA_DEVICE_AUTHENTICATE_INVALID', null, ws._socket.remoteAddress, JSON.stringify({ jwt: cookies.jwt }), null);
|
||||
return false;
|
||||
|
@ -139,8 +137,7 @@ wss.retropilotFunc = {
|
|||
|
||||
try {
|
||||
verifiedJWT = jsonwebtoken.verify(cookies.jwt, device.public_key, { ignoreNotBefore: true });
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
logger.info(`Athena(Websocket) - AUTHENTICATION FAILED (BAD JWT, CHECK SIGNATURE) IP: ${ws._socket.remoteAddress}`);
|
||||
wss.retropilotFunc.actionLogger(null, null, 'ATHENA_DEVICE_AUTHENTICATE_INVALID', null, ws._socket.remoteAddress, JSON.stringify({ jwt: cookies.jwt }), null);
|
||||
return false;
|
||||
|
@ -160,14 +157,14 @@ wss.retropilotFunc = {
|
|||
},
|
||||
|
||||
commandBuilder: (method, params, id) => ({
|
||||
method, params, jsonrpc: '2.0', id
|
||||
method, params, jsonrpc: '2.0', id,
|
||||
}),
|
||||
|
||||
actionLogger: async (account_id, device_id, action, user_ip, device_ip, meta, dongle_id) => {
|
||||
models.models.athena_action_log.create({
|
||||
account_id, device_id, action, user_ip, device_ip, meta, created_at: Date.now(), dongle_id
|
||||
account_id, device_id, action, user_ip, device_ip, meta, created_at: Date.now(), dongle_id,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -13,12 +13,11 @@ async function isDongleOnline(ws, msg) {
|
|||
command: msg.command,
|
||||
success: true,
|
||||
id: msg.id || null,
|
||||
data: athenaRealtime.isDeviceConnected(ws.account.id, null, msg.data.dongleId)
|
||||
data: athenaRealtime.isDeviceConnected(ws.account.id, null, msg.data.dongleId),
|
||||
}));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ws.send(JSON.stringify({
|
||||
command: msg.command, success: false, id: msg.id || null, msg: 'not_authorised'
|
||||
command: msg.command, success: false, id: msg.id || null, msg: 'not_authorised',
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -33,12 +32,11 @@ async function rebootDongle(ws, msg) {
|
|||
if (isAuthorised && isAuthorised.success === true) {
|
||||
await athenaRealtime.invoke('reboot', null, msg.data.dongleId, ws.account.id, msg.id || null);
|
||||
ws.send(JSON.stringify({
|
||||
command: msg.command, success: true, id: msg.id || null, data: { command_issued: true }
|
||||
command: msg.command, success: true, id: msg.id || null, data: { command_issued: true },
|
||||
}));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ws.send(JSON.stringify({
|
||||
command: msg.command, success: false, id: msg.id || null, msg: 'not_authorised'
|
||||
command: msg.command, success: false, id: msg.id || null, msg: 'not_authorised',
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -49,12 +47,11 @@ async function takeSnapshot(ws, msg) {
|
|||
if (isAuthorised && isAuthorised.success === true) {
|
||||
await athenaRealtime.invoke('takeSnapshot', null, msg.data.dongleId, ws.account.id, msg.id || null);
|
||||
ws.send(JSON.stringify({
|
||||
command: msg.command, success: true, id: msg.id || null, data: { command_issued: true }
|
||||
command: msg.command, success: true, id: msg.id || null, data: { command_issued: true },
|
||||
}));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ws.send(JSON.stringify({
|
||||
command: msg.command, success: false, id: msg.id || null, msg: 'not_authorised'
|
||||
command: msg.command, success: false, id: msg.id || null, msg: 'not_authorised',
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -62,5 +59,5 @@ async function takeSnapshot(ws, msg) {
|
|||
module.exports = {
|
||||
isDongleOnline,
|
||||
rebootDongle,
|
||||
takeSnapshot
|
||||
takeSnapshot,
|
||||
};
|
||||
|
|
|
@ -35,6 +35,6 @@ module.exports = (websocket) => {
|
|||
return {
|
||||
getDongleOwners,
|
||||
dongleStatus,
|
||||
passData
|
||||
passData,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -36,7 +36,7 @@ function __server() {
|
|||
|
||||
function buildResponse(ws, success, msg, data) {
|
||||
ws.send(JSON.stringify({
|
||||
success, msg, data, timestamp: Date.now()
|
||||
success, msg, data, timestamp: Date.now(),
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ async function manageConnection(ws, res) {
|
|||
return realtimeCommands.takeSnapshot(ws, msg);
|
||||
default:
|
||||
return ws.send(JSON.stringify({
|
||||
error: true, id: msg.id || null, msg: 'VERIFY_DATA', data: { msg }
|
||||
error: true, id: msg.id || null, msg: 'VERIFY_DATA', data: { msg },
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
@ -100,5 +100,5 @@ athenaRealtime.realtimeCallback(controls);
|
|||
|
||||
module.exports = {
|
||||
controls,
|
||||
websocketServer
|
||||
websocketServer,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue