Added proof of concept for Athena
parent
4075e5730a
commit
9361043d83
|
@ -0,0 +1,130 @@
|
|||
const WebSocket = require('ws');
|
||||
const fs = require('fs');
|
||||
const cookie = require('cookie')
|
||||
const jsonwebtoken = require('jsonwebtoken');
|
||||
|
||||
|
||||
const authenticationController = require('./../controllers/authentication');
|
||||
const deviceController = require('./../controllers/devices');
|
||||
|
||||
let wss;
|
||||
|
||||
async function __server() {
|
||||
wss = new WebSocket.WebSocketServer({ path: '/ws/v2/', port: 4040 });
|
||||
console.log("src")
|
||||
|
||||
|
||||
|
||||
wss.on('connection', manageConnection)
|
||||
|
||||
}
|
||||
|
||||
const authenticateDongle = async (ws, res, cookies) => {
|
||||
unsafeJwt = jsonwebtoken.decode(cookies.jwt);
|
||||
const device = await deviceController.getDeviceFromDongle(unsafeJwt.identity)
|
||||
console.log(unsafeJwt)
|
||||
|
||||
|
||||
let verifiedJWT;
|
||||
|
||||
try {
|
||||
verifiedJWT = jsonwebtoken.verify(cookies.jwt, device.public_key, {ignoreNotBefore: true});
|
||||
} catch (err) {
|
||||
console.log("bad JWT");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (verifiedJWT.identify === unsafeJwt.identify) {
|
||||
ws.dongleId = device.dongle_id
|
||||
console.log("AUTHENTICATED DONGLE")
|
||||
return true;
|
||||
} else {
|
||||
console.log("UNAUTHENTICATED DONGLE");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function commandBuilder(method, params) {
|
||||
|
||||
|
||||
return {
|
||||
method,
|
||||
params,
|
||||
"jsonrpc": "2.0",
|
||||
"id": 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
async function manageConnection(ws, res) {
|
||||
ws.badMessages = 0;
|
||||
var cookies = cookie.parse(res.headers.cookie);
|
||||
|
||||
|
||||
ws.on('message', function incoming(message) {
|
||||
if (!ws.dongleId) { return null; console.log("unauthenticated message, discarded"); }
|
||||
|
||||
console.log("unknown message", JSON.stringify(message))
|
||||
});
|
||||
|
||||
|
||||
if (await authenticateDongle(ws, res, cookies) === false) {
|
||||
ws.close();
|
||||
}
|
||||
|
||||
//ws.send(JSON.stringify(await commandBuilder('reboot')))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
__server();
|
||||
|
||||
|
||||
|
||||
|
||||
function _findSocketFromDongle(dongleId) {
|
||||
|
||||
let websocket = null;
|
||||
wss.clients.forEach((value) => {
|
||||
console.log(value.dongleId)
|
||||
|
||||
if (value.dongleId === dongleId) {
|
||||
websocket = value;
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
return websocket;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function rebootDevice(dongleId) {
|
||||
const websocket = _findSocketFromDongle(dongleId);
|
||||
|
||||
if (!websocket) { return false; console.log("bad")}
|
||||
|
||||
websocket.send(JSON.stringify(commandBuilder('reboot')))
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
rebootDevice
|
||||
}
|
|
@ -8,7 +8,7 @@ async function validateJWT(token, key) {
|
|||
try {
|
||||
return jwt.verify(token.replace("JWT ", ""), key, {algorithms: ['RS256'], ignoreNotBefore: true});
|
||||
} catch (exception) {
|
||||
logger.warn(`failed to validate JWT ${exception}`)
|
||||
console.log(`failed to validate JWT ${exception}`)
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -26,12 +26,9 @@ async function signIn(email, password) {
|
|||
|
||||
let account = await models_orm.models.accounts.findOne({where: {email: email}});
|
||||
|
||||
|
||||
if (account.dataValues) {
|
||||
account = account.dataValues;
|
||||
|
||||
const inputPassword = crypto.createHash('sha256').update(password + config.applicationSalt).digest('hex');
|
||||
|
||||
if (account.password === inputPassword) {
|
||||
const token = jwt.sign({accountId: account.id}, config.applicationSalt)
|
||||
return {success: true, jwt: token};
|
||||
|
@ -44,6 +41,8 @@ async function signIn(email, password) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
async function changePassword(account, newPassword, oldPassword) {
|
||||
if (!account || !newPassword || !oldPassword) { return {success: false, error: 'MISSING_DATA'}}
|
||||
const oldPasswordHash = crypto.createHash('sha256').update(oldPassword + config.applicationSalt).digest('hex')
|
||||
|
@ -101,5 +100,6 @@ module.exports = {
|
|||
validateJWT: validateJWT,
|
||||
getAuthenticatedAccount: getAuthenticatedAccount,
|
||||
changePassword: changePassword,
|
||||
signIn: signIn
|
||||
signIn: signIn,
|
||||
readJWT: readJWT
|
||||
}
|
|
@ -13,7 +13,7 @@ async function pairDevice(account, qr_string) {
|
|||
let deviceQuery;
|
||||
let pairJWT;
|
||||
if (qrCodeParts.length > 0) {
|
||||
deviceQuery = await models_orm.models.device.findOne({ where: { imei: qrCodeParts[0], serial: qrCodeParts[1] }});
|
||||
deviceQuery = await models_orm.models.device.findOne({ where: { serial: qrCodeParts[1] }});
|
||||
pairJWT = qrCodeParts[2];
|
||||
} else {
|
||||
pairJWT = qr_string;
|
||||
|
@ -21,25 +21,42 @@ async function pairDevice(account, qr_string) {
|
|||
deviceQuery = await models_orm.models.device.findOne({ where: { dongle_id: data.identiy }});
|
||||
}
|
||||
|
||||
if (deviceQuery.dataValues == null) {
|
||||
|
||||
if (deviceQuery == null) {
|
||||
return {success: false, registered: false}
|
||||
}
|
||||
|
||||
const device = deviceQuery.dataValues;
|
||||
var decoded = controllers.authentication.validateJWT(pairJWT, device.public_key);
|
||||
var decoded = await authenticationController.validateJWT(pairJWT, device.public_key);
|
||||
if (decoded == null || decoded.pair == undefined) {
|
||||
return {success: false, badToken: true}
|
||||
}
|
||||
|
||||
|
||||
if (device.account_id != 0) {
|
||||
return {success: false, alreadyPaired: true, dongle_id: device.dongle_id}
|
||||
}
|
||||
return await pairDeviceToAccountId(device.dongle_id, account.id )
|
||||
|
||||
}
|
||||
|
||||
const update = models_orm.models.accounts.update(
|
||||
{ account_id: account.id },
|
||||
{ where: { dongle_id: device.dongle_id } }
|
||||
async function pairDeviceToAccountId(dongle_id, account_id) {
|
||||
console.log("input", account_id, dongle_id)
|
||||
const update = await models_orm.models.device.update(
|
||||
{ account_id: account_id },
|
||||
{ where: { dongle_id: dongle_id } }
|
||||
)
|
||||
|
||||
return {success: true, paired: true, dongle_id: device.dongle_id, account_id: account.id}
|
||||
console.log("update:" , update)
|
||||
|
||||
const check = await models_orm.models.device.findOne({where: {dongle_id: dongle_id, account_id: account_id}})
|
||||
console.log(check);
|
||||
if (check.dataValues) {
|
||||
return {success: true, paired: true, dongle_id: dongle_id, account_id: account_id}
|
||||
} else {
|
||||
return {success: false, paired: false}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function unpairDevice(account, dongleId) {
|
||||
|
@ -68,13 +85,15 @@ async function setDeviceNickname(account, dongleId, nickname) {
|
|||
}
|
||||
|
||||
async function getDevices(accountId) {
|
||||
const devices = await models_orm.models.device.getOne({where: {account_id: accountId}});
|
||||
const devices = await models_orm.models.device.findAll();
|
||||
|
||||
return devices.dataValues || null
|
||||
console.log("kkk", devices);
|
||||
|
||||
return devices.dataValues
|
||||
}
|
||||
|
||||
async function getDeviceFromDongle(dongleId) {
|
||||
const devices = await models_orm.models.device.getOne({where: {dongle_id: dongleId}});
|
||||
const devices = await models_orm.models.device.findOne({where: {dongle_id: dongleId}});
|
||||
|
||||
return devices.dataValues || null
|
||||
}
|
||||
|
@ -91,10 +110,9 @@ async function setIgnoredUploads(dongleId, isIgnored) {
|
|||
}
|
||||
|
||||
async function getAllDevicesFiltered() {
|
||||
console.log(models_orm.models.device)
|
||||
const devices = await models_orm.models.device.findAll();
|
||||
|
||||
return devices.dataValues || null
|
||||
return devices
|
||||
}
|
||||
|
||||
|
||||
|
@ -106,4 +124,5 @@ module.exports = {
|
|||
getDeviceFromDongle,
|
||||
setIgnoredUploads,
|
||||
getAllDevicesFiltered,
|
||||
pairDeviceToAccountId,
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ module.exports = async (models, logger, models_sqli) => {
|
|||
helpers: require('./helpers')(models, logger),
|
||||
storage: require('./storage')(models, logger),
|
||||
mailing: require('./mailing')(models, logger),
|
||||
users: require('./users')(models, logger),
|
||||
users: require('./users'),
|
||||
admin: require('./admin'),
|
||||
devices: require('./devices')
|
||||
}
|
||||
|
|
|
@ -2,8 +2,7 @@ const config = require('./../config');
|
|||
const crypto = require('crypto');
|
||||
const models_orm = require('./../models/index.model');
|
||||
const authentication = require('./authentication');
|
||||
let models;
|
||||
let logger;
|
||||
|
||||
|
||||
|
||||
async function getAccountFromId(id) {
|
||||
|
@ -70,14 +69,9 @@ async function getAllUsers() {
|
|||
|
||||
|
||||
|
||||
module.exports = (_models, _logger) => {
|
||||
models = _models;
|
||||
logger = _logger;
|
||||
|
||||
return {
|
||||
module.exports = {
|
||||
createAccount,
|
||||
verifyEmailToken,
|
||||
getAccountFromId,
|
||||
getAllUsers
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"@sendgrid/client": "^7.4.3",
|
||||
"chai": "^4.3.4",
|
||||
"chai-http": "^4.3.0",
|
||||
"cookie": "^0.4.1",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"cors": "^2.8.5",
|
||||
"crypto": "^1.0.1",
|
||||
|
@ -21,6 +22,7 @@
|
|||
"esm": "^3.2.25",
|
||||
"express": "^4.17.1",
|
||||
"express-fileupload": "^1.2.1",
|
||||
"express-ws": "^5.0.2",
|
||||
"fast-folder-size": "^1.3.0",
|
||||
"ffprobe": "^1.1.2",
|
||||
"ffprobe-static": "^3.0.0",
|
||||
|
@ -36,6 +38,8 @@
|
|||
"sequelize": "^6.6.5",
|
||||
"sqlite": "^4.0.22",
|
||||
"sqlite3": "^5.0.2",
|
||||
"supertest": "^6.1.3"
|
||||
"supertest": "^6.1.3",
|
||||
"websocket": "^1.0.34",
|
||||
"ws": "^8.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ const bodyParser = require('body-parser');
|
|||
const crypto = require('crypto');
|
||||
const { route } = require('../../server');
|
||||
const config = require('./../../config');
|
||||
|
||||
const deviceController = require('./../../controllers/devices')
|
||||
|
||||
function runAsyncWrapper(callback) {
|
||||
return function (req, res, next) {
|
||||
|
@ -66,20 +66,25 @@ router.get('/device/:dongle_id', runAsyncWrapper(async (req, res) => {
|
|||
|
||||
}));
|
||||
|
||||
router.get('/device', runAsyncWrapper(async (req, res) => {
|
||||
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)
|
||||
|
||||
return res.status(200).json({success: true, data: await controllers.devices.getAllDevicesFiltered()})
|
||||
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})
|
||||
|
||||
}));
|
||||
|
||||
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})}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}));
|
||||
|
||||
router.get('/admin/device/:dongle_id/ignore/:ignore_uploads', runAsyncWrapper(async (req, res) => {
|
||||
|
@ -107,6 +112,12 @@ router.get('/admin/device/:dongle_id/ignore/:ignore_uploads', runAsyncWrapper(as
|
|||
}));
|
||||
|
||||
|
||||
router.get('/device/:dongle_id/athena/reboot', runAsyncWrapper(async (req, res) => {
|
||||
|
||||
req.athenaWebsocketTemp.rebootDevice(req.params.dongle_id)
|
||||
res.send("ok");
|
||||
|
||||
}));
|
||||
|
||||
|
||||
module.exports = (_models, _controllers, _logger) => {
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
const router = require('express').Router();
|
||||
const config = require('./../config');
|
||||
|
||||
const authenticationController = require('./../../controllers/authentication');
|
||||
const userController = require('./../../controllers/users');
|
||||
|
||||
|
||||
|
||||
|
||||
function runAsyncWrapper(callback) {
|
||||
return function (req, res, next) {
|
||||
callback(req, res, next)
|
||||
.catch(next)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
router.post('/retropilot/0/useradmin/auth', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
const signIn = await authentication.signIn(req.body.email, req.body.password)
|
||||
|
||||
if (signIn.success) {
|
||||
res.cookie('jwt', signIn.jwt, {signed: true});
|
||||
res.redirect('/useradmin/overview');
|
||||
} else {
|
||||
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid credentials or banned account'));
|
||||
}
|
||||
}))
|
||||
|
||||
|
||||
router.get('/retropilot/0/useradmin/signout', runAsyncWrapper(async (req, res) => {
|
||||
res.clearCookie('session');
|
||||
return res.json({success: true});
|
||||
}))
|
||||
|
||||
router.get('/session/get', runAsyncWrapper(async (req, res) => {
|
||||
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||
|
||||
if (!account) {
|
||||
res.json({success: true, hasSession: false, session: {}})
|
||||
} else {
|
||||
res.json({success: true, hasSession: false, session: account})
|
||||
|
||||
}
|
||||
|
||||
}))
|
||||
|
||||
module.exports = router
|
|
@ -0,0 +1,38 @@
|
|||
const router = require('express').Router();
|
||||
const config = require('./../../config');
|
||||
|
||||
const userController = require('./../../controllers/users')
|
||||
|
||||
router.post('/retropilot/0/register/email', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
if (!req.body.hasOwnProperty('email') || req.body.email === "" || !req.body.hasOwnProperty('password') || req.body.password === "") {
|
||||
res.json({success: false, msg: 'malformed request'}).status(400);
|
||||
logger.warn("/useradmin/register/token - Malformed Request!")
|
||||
return;
|
||||
}
|
||||
|
||||
const accountStatus = await controllers.users.createAccount(req.body.email, req.body.password);
|
||||
|
||||
if (accountStatus && accountStatus.status) {
|
||||
return res.json(accountStatus).status(accountStatus.status)
|
||||
} else {
|
||||
return res.json({success: false, msg: 'contact server admin'}).status(500);
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
router.get('/retropilot/0/register/verify/:token', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
if (!req.params.token) {
|
||||
res.json({success: false, status: 400, data: {missingToken: true}}).status(400);
|
||||
}
|
||||
|
||||
const verified = await userController.verifyEmailToken(req.params.token)
|
||||
|
||||
if (verified && verified.status) {
|
||||
return res.json(verified).status(verified.status)
|
||||
} else {
|
||||
return res.json({success: false, msg: 'contact server admin'}).status(500);
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
module.exports = router;
|
|
@ -22,13 +22,14 @@ let logger;
|
|||
|
||||
|
||||
router.post('/retropilot/0/useradmin/auth', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
const account = await models.__db.get('SELECT * FROM accounts WHERE email = ? AND password = ?', req.body.email, crypto.createHash('sha256').update(req.body.password + config.applicationSalt).digest('hex'));
|
||||
const signIn = await controllers.authentication.signIn(req.body.email, req.body.password)
|
||||
|
||||
if (!account || account.banned) {
|
||||
return res.json({success: false, msg: account ? 'BANNED' : 'INVALID ACCOUNT'}).status(401);
|
||||
if (signIn.success) {
|
||||
res.cookie('jwt', signIn.jwt, {signed: true});
|
||||
res.redirect('/useradmin/overview');
|
||||
} else {
|
||||
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid credentials or banned account'));
|
||||
}
|
||||
res.cookie('session', {account: account.email, expires: Date.now() + 1000 * 3600 * 24 * 365}, {signed: true});
|
||||
res.json({success: true})
|
||||
}))
|
||||
|
||||
|
||||
|
@ -65,60 +66,6 @@ router.get('/retropilot/0/useradmin', runAsyncWrapper(async (req, res) => {
|
|||
Requires username and password to register
|
||||
*/
|
||||
|
||||
router.post('/retropilot/0/register/email', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
if (!req.body.hasOwnProperty('email') || req.body.email === "" || !req.body.hasOwnProperty('password') || req.body.password === "") {
|
||||
res.json({success: false, msg: 'malformed request'}).status(400);
|
||||
logger.warn("/useradmin/register/token - Malformed Request!")
|
||||
return;
|
||||
}
|
||||
|
||||
const accountStatus = await controllers.users.createAccount(req.body.email, req.body.password);
|
||||
|
||||
if (accountStatus && accountStatus.status) {
|
||||
return res.json(accountStatus).status(accountStatus.status)
|
||||
} else {
|
||||
return res.json({success: false, msg: 'contact server admin'}).status(500);
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
router.get('/retropilot/0/register/verify/:token', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
if (!req.params.token) {
|
||||
res.json({success: false, status: 400, data: {missingToken: true}}).status(400);
|
||||
}
|
||||
|
||||
const verified = await controllers.users.verifyEmailToken(req.params.token)
|
||||
|
||||
console.log(verified);
|
||||
|
||||
if (verified && verified.status) {
|
||||
return res.json(verified).status(verified.status)
|
||||
} else {
|
||||
return res.json({success: false, msg: 'contact server admin'}).status(500);
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
router.get('/retropilot/0/dongle/:dongle_id/nickname/:nickname', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
if (!req.params.nickname || !req.params.dongle_id) {
|
||||
return res.json({success: false, status: 400, msg: 'MISSING PRAMS'}).status(400);
|
||||
}
|
||||
|
||||
const account = await controllers.authentication.getAuthenticatedAccount(req, res);
|
||||
if (account == null) {
|
||||
return res.redirect('/useradmin?status=' + encodeURIComponent('Invalid or expired session'));
|
||||
|
||||
}
|
||||
|
||||
const setNickname = await controllers.devices.setDeviceNickname(account, req.params.dongle_id, req.params.nickname)
|
||||
if (setNickname.status === true) {
|
||||
res.json({success: true, data: {nickname: setNickname.data.nickname}})
|
||||
}
|
||||
}));
|
||||
|
||||
/*
|
||||
router.post('/useradmin/register/token', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||
|
|
|
@ -241,7 +241,7 @@ router.get('/useradmin/unpair_device/:dongleId', runAsyncWrapper(async (req, res
|
|||
return;
|
||||
}
|
||||
|
||||
const pairDevice = await controllers.devices.pairDevice(req.body.qr_string);
|
||||
const pairDevice = await controllers.devices.pairDevice(account, req.body.qr_string);
|
||||
|
||||
if (pairDevice.success === true) {
|
||||
res.redirect('/useradmin/overview');
|
||||
|
|
21
server.js
21
server.js
|
@ -40,6 +40,11 @@ function runAsyncWrapper(callback) {
|
|||
const app = express();
|
||||
|
||||
|
||||
|
||||
|
||||
const athena = require('./Anetha/index');
|
||||
|
||||
|
||||
const web = async () => {
|
||||
// TODO clean up
|
||||
const _models = await models(logger);
|
||||
|
@ -57,10 +62,16 @@ const web = async () => {
|
|||
app.use(routers.api);
|
||||
app.use(routers.useradmin);
|
||||
|
||||
app.use((req, res, next) => {
|
||||
|
||||
req.athenaWebsocketTemp = athena;
|
||||
return next();
|
||||
});
|
||||
|
||||
|
||||
app.use('/admin', routers.admin);
|
||||
|
||||
//if (config.flags.useUserAdminApi) app.use(routers.useradminapi);
|
||||
//app.use(routers.useradminapi)
|
||||
|
||||
|
||||
|
||||
app.use(cors());
|
||||
|
@ -84,14 +95,14 @@ const web = async () => {
|
|||
|
||||
app.get('*', runAsyncWrapper(async (req, res) => {
|
||||
logger.error("HTTP.GET unhandled request: " + controllers.helpers.simpleStringify(req) + ", " + controllers.helpers.simpleStringify(res) + "")
|
||||
res.status(400);
|
||||
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(400);
|
||||
res.status(404);
|
||||
res.send('Not Implemented');
|
||||
}));
|
||||
|
||||
|
@ -113,8 +124,6 @@ lockfile.lock('retropilot_server.lock', {realpath: false, stale: 30000, update:
|
|||
var httpsServer = https.createServer(sslCredentials, app);
|
||||
|
||||
|
||||
|
||||
|
||||
httpServer.listen(config.httpPort, config.httpInterface, () => {
|
||||
logger.info(`Retropilot Server listening at http://` + config.httpInterface + `:` + config.httpPort)
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue