Skip to content

Commit

Permalink
Merge pull request #18 from versx/develop
Browse files Browse the repository at this point in the history
Release 1.5
  • Loading branch information
versx authored Apr 25, 2020
2 parents 4486c92 + fc07d10 commit e7ea997
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 63 deletions.
2 changes: 2 additions & 0 deletions migrations/5.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE `devices` ADD COLUMN `ios_version` VARCHAR(64) DEFAULT NULL;
ALTER TABLE `devices` ADD COLUMN `ipa_version` VARCHAR(64) DEFAULT NULL;
34 changes: 30 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ const apiRoutes = require('./routes/api.js');
const timezones = require('../static/data/timezones.json');

// TODO: Create route classes
// TODO: iOS and IPA version
// TODO: Fix devices scroll with DataTables
// TODO: Fix dropdown closes when table freshes
// TODO: Secure /api/config/:uuid endpoint with token
// TODO: Provider option to show/hide config options
// TODO: Accomodate for # in uuid name

const defaultData = {
title: config.title,
Expand All @@ -36,6 +37,7 @@ dbMigrator.load();
app.set('view engine', 'mustache');
app.set('views', path.resolve(__dirname, 'views'));
app.engine('mustache', mustacheExpress());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false, limit: '50mb' })); // for parsing application/x-www-form-urlencoded
//app.use(bodyParser.raw({ type: 'application/x-www-form-urlencoded' }));
app.use(express.static(path.resolve(__dirname, '../static')));
Expand All @@ -53,7 +55,7 @@ app.use('/api', apiRoutes);

// Login middleware
app.use(function(req, res, next) {
if (req.path === '/api/login' || req.path === '/login' || req.path.includes('/api/config/')) {
if (req.path === '/api/login' || req.path === '/login' || req.path.includes('/api/config')) {
return next();
}
if (req.session.loggedin) {
Expand Down Expand Up @@ -256,7 +258,31 @@ app.get('/schedule/delete/:name', function(req, res) {

// Settings UI Routes
app.get('/settings', function(req, res) {
res.render('settings', defaultData);
var data = defaultData;
data.title = config.title;
data.host = config.db.host;
data.port = config.db.port;
data.username = config.db.username;
data.password = config.db.password;
data.database = config.db.database;
data.charset = config.db.charset;
data.styles = [
{ 'name': 'dark' },
{ 'name': 'light' }
];
data.styles.forEach(function(style) {
style.selected = style.name === config.style;
});
data.languages = [
{ 'name': 'en' },
{ 'name': 'es' }
];
data.languages.forEach(function(locale) {
locale.selected = locale.name === config.locale;
});
data.logging = config.logging ? 'checked' : '';
console.log('Settings:', data);
res.render('settings', data);
});

app.listen(config.port, config.interface, () => console.log(`Listening on port ${config.port}...`));
6 changes: 3 additions & 3 deletions src/models/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const query = require('../db.js');

class Config {
constructor(name, backendUrl, dataEndpoints, token, heartbeatMaxTime, minDelayLogout,
accountManager, deployEggs, nearbyTracker, autoLogin, isDefault) {
accountManager, deployEggs, nearbyTracker, autoLogin, isDefault) {
this.name = name;
this.backendUrl = backendUrl;
this.dataEndpoints = dataEndpoints;
Expand Down Expand Up @@ -50,13 +50,13 @@ class Config {
return data;
}
static async create(name, backendUrl, dataEndpoints, token, heartbeatMaxTime, minDelayLogout,
accountManager, deployEggs, nearbyTracker, autoLogin, isDefault) {
accountManager, deployEggs, nearbyTracker, autoLogin, isDefault) {
var sql = `
INSERT INTO configs (name, backend_url, data_endpoints, token, heartbeat_max_time, min_delay_logout,
account_manager, deploy_eggs, nearby_tracker, auto_login, is_default)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
var args = [name, backendUrl, dataEndpoints, token, heartbeatMaxTime, minDelayLogout,
accountManager, deployEggs, nearbyTracker, autoLogin, isDefault];
accountManager, deployEggs, nearbyTracker, autoLogin, isDefault];
var result = await query(sql, args);
return result.affectedRows === 1;
}
Expand Down
28 changes: 17 additions & 11 deletions src/models/device.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@
const query = require('../db.js');

class Device {
constructor(uuid, config, lastSeen, clientip) {
constructor(uuid, config, lastSeen, clientip, iosVersion, ipaVersion) {
this.uuid = uuid;
this.config = config;
this.lastSeen = lastSeen;
this.clientip = clientip;
this.iosVersion = iosVersion;
this.ipaVersion = ipaVersion;
}
static async getAll() {
var devices = await query('SELECT uuid, config, last_seen, clientip FROM devices');
var devices = await query('SELECT uuid, config, last_seen, clientip, ios_version, ipa_version FROM devices');
return devices;
}
static async getByName(uuid) {
var sql = `
SELECT uuid, config, last_seen, clientip
SELECT uuid, config, last_seen, clientip, ios_version, ipa_version
FROM devices
WHERE uuid = ?`;
var args = [uuid];
Expand All @@ -27,21 +29,25 @@ class Device {
result[0].uuid,
result[0].config,
result[0].last_seen,
result[0].clientip
result[0].clientip,
result[0].ios_version,
result[0].ipa_version
);
}
static async create(uuid, config = null, lastSeen = null, clientip = null) {
static async create(uuid, config = null, lastSeen = null, clientip = null, iosVersion = null, ipaVersion = null) {
var sql = `
INSERT INTO devices (uuid, config, last_seen, clientip)
VALUES (?, ?, ?, ?)`;
var args = [uuid, config, lastSeen, clientip];
INSERT INTO devices (uuid, config, last_seen, clientip, ios_version, ipa_version)
VALUES (?, ?, ?, ?, ?, ?)`;
var args = [uuid, config, lastSeen, clientip, iosVersion, ipaVersion];
var result = await query(sql, args);
if (result.affectedRows === 1) {
return new Device(
uuid,
config,
lastSeen,
clientip
clientip,
iosVersion,
ipaVersion
);
}
return null;
Expand All @@ -55,9 +61,9 @@ class Device {
async save() {
var sql = `
UPDATE devices
SET config = ?, last_seen = ?, clientip = ?
SET config = ?, last_seen = ?, clientip = ?, ios_version = ?, ipa_version = ?
WHERE uuid = ?`;
var args = [this.config, this.lastSeen, this.clientip, this.uuid];
var args = [this.config, this.lastSeen, this.clientip, this.iosVersion, this.ipaVersion, this.uuid];
var result = await query(sql, args);
return result.affectedRows === 1;
}
Expand Down
8 changes: 4 additions & 4 deletions src/models/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Log {
this.timestamp = timestamp;
this.message = message;
}
static async getByDevice(uuid) {
static getByDevice(uuid) {
var name = uuid + '.log';
var logFile = path.resolve(logsDir, name);
if (!fs.existsSync(logFile)) {
Expand All @@ -35,7 +35,7 @@ class Log {
});
return logs;
}
static async create(uuid, message) {
static create(uuid, message) {
var name = uuid + '.log';
var logFile = path.resolve(logsDir, name);
var msg = {
Expand All @@ -47,7 +47,7 @@ class Log {
if (err) throw err;
});
}
static async delete(uuid) {
static delete(uuid) {
var name = uuid + '.log';
var logFile = path.resolve(logsDir, name);
if (fs.existsSync(logFile)) {
Expand All @@ -56,7 +56,7 @@ class Log {
}
return false;
}
static async deleteAll() {
static deleteAll() {
fs.readdir(logsDir, function(err, files) {
if (err) throw err;
files.forEach(function(file) {
Expand Down
81 changes: 60 additions & 21 deletions src/routes/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,43 @@ router.post('/account/change_password/:username', async function(req, res) {
});


// Settings API Routes
router.post('/settings/change_ui', function(req, res) {
var data = req.body;
var newConfig = config;
newConfig.title = data.title;
newConfig.locale = data.locale;
newConfig.style = data.style;
newConfig.logging = data.logging === 'on' ? 1 : 0;
fs.writeFileSync(path.resolve(__dirname, '../config.json'), JSON.stringify(newConfig, null, 2));
res.redirect('/settings');
});

router.post('/settings/change_db', function(req, res) {
var data = req.body;
var newConfig = config;
newConfig.db.host = data.host;
newConfig.db.port = data.port;
newConfig.db.username = data.username;
newConfig.db.password = data.password;
newConfig.db.database = data.database;
newConfig.db.charset = data.charset;
fs.writeFileSync(path.resolve(__dirname, '../config.json'), JSON.stringify(newConfig, null, 2));
res.redirect('/settings');
});


// Device API Routes
router.get('/devices', async function(req, res) {
try {
var devices = await Device.getAll();
devices.forEach(function(device) {
var exists = fs.existsSync(path.join(screenshotsDir, device.uuid + '.png'));
var image = exists ? `/screenshots/${device.uuid}.png` : '/img/offline.png';
device.image = `<a href='${image}' target='_blank'><img src='${image}' width='64' height='96'/></a>`;
// Device received a config last 15 minutes
var delta = 15 * 60;
var isOffline = device.last_seen > (Math.round((new Date()).getTime() / 1000) - delta) ? 0 : 1;
var image = exists ? `/screenshots/${device.uuid}.png` : (isOffline ? '/img/offline.png' : '/img/online.png');
device.image = `<a href='${image}' target='_blank'><img src='${image}' width='72' height='96'/></a>`;
device.last_seen = utils.getDateTime(device.last_seen);
device.buttons = `
<div class='btn-group' role='group'>
Expand Down Expand Up @@ -167,12 +196,15 @@ router.get('/configs', async function(req, res) {
}
});

router.get('/config/:uuid', async function(req, res) {
var uuid = req.params.uuid;
router.post('/config', async function(req, res) {
var data = req.body;
var uuid = data.uuid;
var iosVersion = data.ios_version;
var ipaVersion = data.ipa_version;
var device = await Device.getByName(uuid);
var noConfig = false;
var assignDefault = false;
// Check for a proxied IP before the normal IP and set the first one at exists
// Check for a proxied IP before the normal IP and set the first one that exists
var clientip = ((req.headers['x-forwarded-for'] || '').split(', ')[0]) || (req.connection.remoteAddress).match('[0-9]+.[0-9].+[0-9]+.[0-9]+$')[0];
console.log('[' + new Date().toLocaleString() + ']', 'Client', uuid, 'at', clientip, 'is requesting a config.');

Expand All @@ -181,6 +213,8 @@ router.get('/config/:uuid', async function(req, res) {
// Device exists
device.lastSeen = new Date() / 1000;
device.clientip = clientip;
device.iosVersion = iosVersion;
device.ipaVersion = ipaVersion;
device.save();
if (device.config) {
// Nothing to do besides respond with config
Expand All @@ -192,7 +226,8 @@ router.get('/config/:uuid', async function(req, res) {
} else {
console.log('Device does not exist, creating...');
// Device doesn't exist, create db entry
device = await Device.create(uuid, null, new Date() / 1000, clientip); // REVIEW: Maybe return Device object upon creation to prevent another sql call to get Device object?
var ts = new Date() / 1000;
device = await Device.create(uuid, null, ts, clientip, iosVersion, ipaVersion);
if (device) {
// Success, assign default config if there is one.
assignDefault = true;
Expand Down Expand Up @@ -227,11 +262,11 @@ router.get('/config/:uuid', async function(req, res) {
var c = await Config.getByName(device.config);
if (c === null) {
console.error('Failed to grab config', device.config);
var data = {
var noConfigData2 = {
status: 'error',
error: 'Device not assigned to config!'
};
res.send(JSON.stringify(data));
res.send(JSON.stringify(noConfigData2));
return;
}
// Build json config
Expand Down Expand Up @@ -397,9 +432,9 @@ router.get('/schedule/delete_all', function(req, res) {


// Logging API requests
router.get('/logs/:uuid', async function(req, res) {
router.get('/logs/:uuid', function(req, res) {
var uuid = req.params.uuid;
var logs = await Log.getByDevice(uuid);
var logs = Log.getByDevice(uuid);
res.send({
uuid: uuid,
data: {
Expand All @@ -408,33 +443,37 @@ router.get('/logs/:uuid', async function(req, res) {
});
});

router.post('/log/new/:uuid', async function(req, res) {
router.post('/log/new', function(req, res) {
if (config.logging === false) {
// Logs are disabled
res.send('OK');
return;
}
var uuid = req.params.uuid;
var msg = Object.keys(req.body)[0]; // Dumb hack
var result = await Log.create(uuid, msg);
if (result) {
// Success
var uuid = req.body.uuid;
var messages = req.body.messages;
if (messages) {
messages.forEach(function(message) {
var result = Log.create(uuid, message);
if (result) {
// Success
}
console.log('[SYSLOG]', uuid, ':', message);
});
}
console.log('[SYSLOG]', uuid, ':', msg);
res.send('OK');
});

router.get('/log/delete/:uuid', async function(req, res) {
router.get('/log/delete/:uuid', function(req, res) {
var uuid = req.params.uuid;
var result = await Log.delete(uuid);
var result = Log.delete(uuid);
if (result) {
// Success
}
res.redirect('/device/logs/' + uuid);
});

router.get('/logs/delete_all', async function(req, res) {
var result = await Log.deleteAll();
router.get('/logs/delete_all', function(req, res) {
var result = Log.deleteAll();
if (result) {
// Success
}
Expand Down
2 changes: 1 addition & 1 deletion src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function getDateTime(timestamp) {
}

function buildConfig(backendUrl, dataEndpoints, token, heartbeatMaxTime, minDelayLogout,
accountManager, deployEggs, nearbyTracker, autoLogin) {
accountManager, deployEggs, nearbyTracker, autoLogin) {
var obj = {
'backend_url': backendUrl,
'data_endpoints': (dataEndpoints || '').split(',') || [],
Expand Down
14 changes: 12 additions & 2 deletions src/views/device-manage.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,23 @@
}
function get(url, id) {
if (url.includes('/screen')) {
}
var isScreen = url.includes('/screen');
$.ajax({
url: url,
type: 'GET',
dataType: 'json',
dataType: isScreen ? 'image/jpeg' : 'json',
success: function (data) {
console.log("Ajax response:", data);
$('#' + id).text(JSON.stringify(data, null, 2));
if (isScreen) {
img = new Image();
img.src = data;
$('#' + id).append(img);
} else {
$('#' + id).text(JSON.stringify(data, null, 2));
}
},
error: function (error) {
console.log("Error:", error);
Expand Down
Loading

0 comments on commit e7ea997

Please sign in to comment.