diff --git a/config.example.json b/config.example.json index 1a1e8a2..2181778 100644 --- a/config.example.json +++ b/config.example.json @@ -9,6 +9,6 @@ "username": "user123", "password": "pass123", "database": "dcm", - "charset": "utf8" + "charset": "utf8mb4" } } \ No newline at end of file diff --git a/db.js b/db.js index dad492c..5ad3779 100644 --- a/db.js +++ b/db.js @@ -13,7 +13,7 @@ function getConnection() { charset: config.db.charset }); - conn.connect(err => { + conn.connect(function(err) { if (err) { console.log('Error connecting to database'); return; @@ -31,7 +31,7 @@ function query(sql, args) { // The Promise constructor should catch any errors thrown on // this tick. Alternately, try/catch and reject(err) on catch. var conn = getConnection(); - conn.query(sql, args, function (err, rows, fields) { + conn.query(sql, args, function(err, rows, fields) { // Call reject on error states, // call resolve with results if (err) { diff --git a/index.js b/index.js index 88efae8..eabf1d5 100644 --- a/index.js +++ b/index.js @@ -14,6 +14,7 @@ const Log = require('./models/log.js'); // TODO: Error checking/handling // TODO: Security / token auth // TODO: Default config for devices, auto assigned? +// TODO: If default config is set, assign to device // Middleware app.set('view engine', 'mustache'); @@ -68,42 +69,38 @@ app.get('/config/new', function(req, res) { }); app.get('/config/edit/:name', async function(req, res) { - var name = req.params.name; - var sql = "SELECT backend_url, port, heartbeat_max_time, pokemon_max_time, raid_max_time, startup_lat, startup_lon, token, jitter_value, max_warning_time_raid, encounter_delay, min_delay_logout, max_empty_gmo, max_failed_count, max_no_quest_count, logging_url, logging_port, logging_tls, logging_tcp, account_manager, deploy_eggs, nearby_tracker, auto_login, ultra_iv, ultra_quests FROM config WHERE name=? LIMIT 1"; - var args = [name]; - var cfg = await query(sql, args); - // TODO: Error checking - var c = cfg[0]; - c.name = name; + var name = req.params.name; + var c = await Config.getByName(name); var data = { title: config.title, old_name: name, - name: name, - backend_url: c.backend_url, + name: c.name, + backend_url: c.backendUrl, port: c.port, - heartbeat_max_time: c.heartbeat_max_time, - pokemon_max_time: c.pokemon_max_time, - raid_max_time: c.raid_max_time, - startup_lat: c.startup_lat, - startup_lon: c.startup_lon, + heartbeat_max_time: c.heartbeatMaxTime, + pokemon_max_time: c.pokemonMaxTime, + raid_max_time: c.raidMaxTime, + startup_lat: c.startupLat, + startup_lon: c.startupLon, token: c.token, - jitter_value: c.jitter_value, - max_warning_time_raid: c.max_warning_time_raid, - encounter_delay: c.encounter_delay, - min_delay_logout: c.min_delay_logout, - max_empty_gmo: c.max_empty_gmo, - max_failed_count: c.max_failed_count, - max_no_quest_count: c.max_no_quest_count, - logging_url: c.logging_url, - logging_port: c.logging_port, - logging_tls: c.logging_tls === 1 ? "checked" : "", - logging_tcp: c.logging_tcp === 1 ? "checked" : "", - account_manager: c.account_manager === 1 ? "checked" : "", - deploy_eggs: c.deploy_eggs === 1 ? "checked" : "", - nearby_tracker: c.nearby_tracker === 1 ? "checked" : "", - auto_login: c.auto_login === 1 ? "checked" : "", - ultra_iv: c.ultra_iv === 1 ? "checked" : "", - ultra_quests: c.ultra_quests === 1 ? "checked" : "" + jitter_value: c.jitterValue, + max_warning_time_raid: c.maxWarningTimeRaid, + encounter_delay: c.encounterDelay, + min_delay_logout: c.minDelayLogout, + max_empty_gmo: c.maxEmptyGmo, + max_failed_count: c.maxFailedCount, + max_no_quest_count: c.maxNoQuestCount, + logging_url: c.loggingUrl, + logging_port: c.loggingPort, + logging_tls: c.loggingTls === 1 ? "checked" : "", + logging_tcp: c.loggingTcp === 1 ? "checked" : "", + account_manager: c.accountManager === 1 ? "checked" : "", + deploy_eggs: c.deployEggs === 1 ? "checked" : "", + nearby_tracker: c.nearbyTracker === 1 ? "checked" : "", + auto_login: c.autoLogin === 1 ? "checked" : "", + ultra_iv: c.ultraIV === 1 ? "checked" : "", + ultra_quests: c.ultraQuests === 1 ? "checked" : "", + is_default: c.isDefault === 1 ? "checked" : "" }; res.render('config-edit', data); }); @@ -141,7 +138,10 @@ app.get('/api/devices', async function(req, res) { app.post('/api/device/new', async function(req, res) { var uuid = req.body.uuid; var config = req.body.config; - var result = await Device.create(uuid, config || null, null) + var result = await Device.create(uuid, config || null, null) + if (result) { + // Success + } console.log("New device result:", result); res.redirect('/devices'); }); @@ -160,6 +160,7 @@ app.get('/api/configs', async function(req, res) { try { var configs = await Config.getAll(); configs.forEach(function(config) { + config.is_default = config.is_default ? "Yes" : "No"; config.buttons = " \ "; }); @@ -171,6 +172,113 @@ app.get('/api/configs', async function(req, res) { }); app.get('/api/config/:uuid', async function(req, res) { + // TODO: Device says hello, db checks if it exists. + // TODO: If device does exist, check if it has been assigned a config. + // TODO: - if device is assigned config, send it. If it isn't attempt the assign default config if there is one. + // TODO: if device does not exist, create it and attempt to assign default config if there is one. + + var uuid = req.params.uuid; + var device = await Device.getByName(uuid); + var noConfig = false; + // Check if device config is empty, if not provide it as json response + if (device) { + // Device exists + device.lastSeen = new Date() / 1000; + device.save(); + if (device.config) { + // Do something + } else { + console.log("Device", uuid, "not assigned a config, attempting to assign the default config if one is set..."); + // Not assigned a config + var defaultConfig = await Config.getDefault(); + if (defaultConfig !== null) { + console.log("Assigning device", uuid, "default config", defaultConfig.name); + device.config = defaultConfig.name; + device.save(); + } else { + // No default config so don't give config response + noConfig = true; + } + } + } else { + console.log("Device doesn't exist, creating..."); + // Device doesn't exist, create db entry + var result = await Device.create(uuid); + if (result) { + // Success, assign default config if there is one. + var defaultConfig = await Config.getDefault(); + if (defaultConfig !== null) { + console.log("Assigning device", uuid, "default config", defaultConfig.name); + device = await Device.getByName(uuid); + device.config = defaultConfig.name; + device.save(); + } else { + // No default config so don't give config response + noConfig = true; + } + } else { + // Failed to create device so don't give config response + noConfig = true; + } + } + + if (noConfig) { + console.log("No config assigned to device", uuid, "and no default config to assign!"); + var data = { + status: "error", + error: "Device not assigned to config!" + } + var json = JSON.stringify(data); + res.send(json); + return; + } + + // TODO: Use Config.getByName instead + var sql = "SELECT * FROM config WHERE name = ? LIMIT 1"; + var args = [device.config]; + var configs = await query(sql, args); + if (configs.length > 0) { + var c = configs[0]; + // Build json config + var json = buildConfig( + c.backend_url, + c.port, + c.heartbeat_max_time, + c.pokemon_max_time, + c.raid_max_time, + c.startup_lat, + c.startup_lon, + c.token, + c.jitter_value, + c.max_warning_time_raid, + c.encounter_delay, + c.min_delay_logout, + c.max_empty_gmo, + c.max_failed_count, + c.max_no_quest_count, + c.logging_url, + c.logging_port, + c.logging_tls, + c.logging_tcp, + c.account_manager, + c.deploy_eggs, + c.nearby_tracker, + c.auto_login, + c.ultra_iv, + c.ultra_quests, + c.is_default + ); + console.log("Config response:", json); + res.send(json); + } +}); + +app.get('/api/config/:uuid', async function(req, res) { + // TODO: Device says hello, db checks if it exists. + // TODO: If device does exist, check if it has been assigned a config. + // TODO: - if device is assigned config, send it. If it isn't attempt the assign default config if there is one. + // TODO: if device does not exist, create it and attempt to assign default config if there is one. + var uuid = req.params.uuid; var device = await Device.getByName(uuid); // Check if device config is empty, if not provide it as json response @@ -178,6 +286,7 @@ app.get('/api/config/:uuid', async function(req, res) { device.lastSeen = new Date() / 1000; device.save(); if (device.config) { + // TODO: Use Config.getByName instead var sql = "SELECT * FROM config WHERE name = ? LIMIT 1"; var args = [device.config]; var configs = await query(sql, args); @@ -209,7 +318,8 @@ app.get('/api/config/:uuid', async function(req, res) { c.nearby_tracker, c.auto_login, c.ultra_iv, - c.ultra_quests, + c.ultra_quests, + c.is_default ); console.log("Config response:", json); res.send(json); @@ -278,7 +388,8 @@ app.post('/api/config/new', async function(req, res) { data.nearby_tracker === 'on' ? 1 : 0, data.auto_login === 'on' ? 1 : 0, data.ultra_iv === 'on' ? 1 : 0, - data.ultra_quests === 'on' ? 1 : 0, + data.ultra_quests === 'on' ? 1 : 0, + data.is_default === 'on' ? 1 : 0 ); if (result) { console.log("Config inserted"); @@ -310,16 +421,20 @@ app.post('/api/config/edit/:name', async function(req, res) { c.maxNoQuestCount = data.max_no_quest_count; c.loggingUrl = data.logging_url; c.loggingPort = data.logging_port; - c.loggingTls = data.logging_tls === "on" ? 1 : 0; - c.loggingTcp = data.logging_tcp === "on" ? 1 : 0; - c.accountManager = data.account_manager === "on" ? 1 : 0; - c.deployEggs = data.deploy_eggs === "on" ? 1 : 0; - c.nearbyTracker = data.nearby_tracker === "on" ? 1 : 0; - c.autoLogin = data.auto_login === "on" ? 1 : 0; - c.ultraIV = data.ultra_iv === "on" ? 1 : 0; - c.ultraQuests = data.ultra_quests === "on" ? 1 : 0; + c.loggingTls = data.logging_tls === 'on' ? 1 : 0; + c.loggingTcp = data.logging_tcp === 'on' ? 1 : 0; + c.accountManager = data.account_manager === 'on' ? 1 : 0; + c.deployEggs = data.deploy_eggs === 'on' ? 1 : 0; + c.nearbyTracker = data.nearby_tracker === 'on' ? 1 : 0; + c.autoLogin = data.auto_login === 'on' ? 1 : 0; + c.ultraIV = data.ultra_iv === 'on' ? 1 : 0; + c.ultraQuests = data.ultra_quests === 'on' ? 1 : 0; + c.isDefault = data.is_default === 'on' ? 1 : 0; if (await c.save(oldName)) { - // Success + // Success + if (c.isDefault !== false) { + await Config.setDefault(oldName); + } } res.redirect('/configs'); }); diff --git a/models/config.js b/models/config.js index 5f94eb2..4906e38 100644 --- a/models/config.js +++ b/models/config.js @@ -3,7 +3,9 @@ const query = require('../db.js'); class Config { - constructor(name, backendUrl, port, heartbeatMaxTime, pokemonMaxTime, raidMaxTime, startupLat, startupLon, token, jitterValue, maxWarningTimeRaid, encounterDelay, minDelayLogout, maxEmptyGmo, maxFailedCount, maxNoQuestCount, loggingUrl, loggingPort, loggingTls, loggingTcp, accountManager, deployEggs, nearbyTracker, autoLogin, ultraIV, ultraQuests) { + constructor(name, backendUrl, port, heartbeatMaxTime, pokemonMaxTime, raidMaxTime, startupLat, startupLon, token, jitterValue, + maxWarningTimeRaid, encounterDelay, minDelayLogout, maxEmptyGmo, maxFailedCount, maxNoQuestCount, loggingUrl, + loggingPort, loggingTls, loggingTcp, accountManager, deployEggs, nearbyTracker, autoLogin, ultraIV, ultraQuests, isDefault) { this.name = name; this.backendUrl = backendUrl; this.port = port; @@ -30,18 +32,21 @@ class Config { this.autoLogin = autoLogin; this.ultraIV = ultraIV; this.ultraQuests = ultraQuests; + this.isDefault = isDefault; } static async getAll() { var configs = await query("SELECT * FROM config"); return configs; } static async getByName(name) { - var sql = "SELECT backend_url, port, heartbeat_max_time, pokemon_max_time, raid_max_time, startup_lat, startup_lon, token, jitter_value, \ - max_warning_time_raid, encounter_delay, min_delay_logout, max_empty_gmo, max_failed_count, max_no_quest_count, logging_url, \ - logging_port, logging_tls, logging_tcp, account_manager, deploy_eggs, nearby_tracker, auto_login, ultra_iv, ultra_quests \ - FROM config \ - WHERE name = ? \ - LIMIT 1"; + var sql = ` + SELECT backend_url, port, heartbeat_max_time, pokemon_max_time, raid_max_time, startup_lat, startup_lon, token, jitter_value, + max_warning_time_raid, encounter_delay, min_delay_logout, max_empty_gmo, max_failed_count, max_no_quest_count, logging_url, + logging_port, logging_tls, logging_tcp, account_manager, deploy_eggs, nearby_tracker, auto_login, ultra_iv, ultra_quests, + is_default + FROM config + WHERE name = ? + LIMIT 1`; var args = [name]; var result = await query(sql, args); // TODO: Error checking @@ -73,14 +78,23 @@ class Config { c.nearby_tracker, c.auto_login, c.ultra_iv, - c.ultra_quests + c.ultra_quests, + c.is_default ); return data; } - static async create(name, backendUrl, port, heartbeatMaxTime, pokemonMaxTime, raidMaxTime, startupLat, startupLon, token, jitterValue, maxWarningTimeRaid, encounterDelay, minDelayLogout, maxEmptyGmo, maxFailedCount, maxNoQuestCount, loggingUrl, loggingPort, loggingTls, loggingTcp, accountManager, deployEggs, nearbyTracker, autoLogin, ultraIV, ultraQuests) { - var sql = "INSERT INTO config (name, backend_url, port, heartbeat_max_time, pokemon_max_time, raid_max_time, startup_lat, startup_lon, token, jitter_value, max_warning_time_raid, encounter_delay, min_delay_logout, max_empty_gmo, max_failed_count, max_no_quest_count, logging_url, logging_port, logging_tls, logging_tcp, account_manager, deploy_eggs, nearby_tracker, auto_login, ultra_iv, ultra_quests)" + - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - var args = [name, backendUrl, port, heartbeatMaxTime, pokemonMaxTime, raidMaxTime, startupLat, startupLon, token, jitterValue, maxWarningTimeRaid, encounterDelay, minDelayLogout, maxEmptyGmo, maxFailedCount, maxNoQuestCount, loggingUrl, loggingPort, loggingTls, loggingTcp, accountManager, deployEggs, nearbyTracker, autoLogin, ultraIV, ultraQuests]; + static async create(name, backendUrl, port, heartbeatMaxTime, pokemonMaxTime, raidMaxTime, startupLat, startupLon, token, jitterValue, + maxWarningTimeRaid, encounterDelay, minDelayLogout, maxEmptyGmo, maxFailedCount, maxNoQuestCount, loggingUrl, loggingPort, + loggingTls, loggingTcp, accountManager, deployEggs, nearbyTracker, autoLogin, ultraIV, ultraQuests, isDefault) { + var sql = ` + INSERT INTO config (name, backend_url, port, heartbeat_max_time, pokemon_max_time, raid_max_time, startup_lat, startup_lon, token, jitter_value, + max_warning_time_raid, encounter_delay, min_delay_logout, max_empty_gmo, max_failed_count, max_no_quest_count, logging_url, + logging_port, logging_tls, logging_tcp, account_manager, deploy_eggs, nearby_tracker, auto_login, ultra_iv, ultra_quests, + is_default) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`; + var args = [name, backendUrl, port, heartbeatMaxTime, pokemonMaxTime, raidMaxTime, startupLat, startupLon, token, jitterValue, + maxWarningTimeRaid, encounterDelay, minDelayLogout, maxEmptyGmo, maxFailedCount, maxNoQuestCount, loggingUrl, loggingPort, + loggingTls, loggingTcp, accountManager, deployEggs, nearbyTracker, autoLogin, ultraIV, ultraQuests, isDefault]; var result = await query(sql, args); return result.affectedRows === 1; } @@ -90,8 +104,70 @@ class Config { var result = await query(sql, args); return result.affectedRows === 1; } + static async getDefault() { + var sql = ` + SELECT name, backend_url, port, heartbeat_max_time, pokemon_max_time, raid_max_time, startup_lat, startup_lon, token, jitter_value, + max_warning_time_raid, encounter_delay, min_delay_logout, max_empty_gmo, max_failed_count, max_no_quest_count, logging_url, + logging_port, logging_tls, logging_tcp, account_manager, deploy_eggs, nearby_tracker, auto_login, ultra_iv, ultra_quests, + is_default + FROM config + WHERE is_default = 1 + LIMIT 1`; + var result = await query(sql, []); + if (result.length === 0) { + return null; + } + var c = result[0]; + var data = new Config( + c.name, + c.backend_url, + c.port, + c.heartbeat_max_time, + c.pokemon_max_time, + c.raid_max_time, + c.startup_lat, + c.startup_lon, + c.token, + c.jitter_value, + c.max_warning_time_raid, + c.encounter_delay, + c.min_delay_logout, + c.max_empty_gmo, + c.max_failed_count, + c.max_no_quest_count, + c.logging_url, + c.logging_port, + c.logging_tls, + c.logging_tcp, + c.account_manager, + c.deploy_eggs, + c.nearby_tracker, + c.auto_login, + c.ultra_iv, + c.ultra_quests, + c.is_default + ); + return data; + } + static async setDefault(name) { + // TODO: Update both in one sql statement + var sql = "UPDATE config SET is_default = 0 WHERE name != ?"; + var args = [name]; + var result = await query(sql, args); + if (result.affectedRows > 0) { + // Success + } + sql = "UPDATE config SET is_default = 1 WHERE name = ?"; + result = await query(sql, args); + return result.affectedRows === 1; + } async save(oldName) { - var sql = "UPDATE config SET name=?, backend_url=?, port=?, heartbeat_max_time=?, pokemon_max_time=?, raid_max_time=?, startup_lat=?, startup_lon=?, token=?, jitter_value=?, max_warning_time_raid=?, encounter_delay=?, min_delay_logout=?, max_empty_gmo=?, max_failed_count=?, max_no_quest_count=?, logging_url=?, logging_port=?, logging_tls=?, logging_tcp=?, account_manager=?, deploy_eggs=?, nearby_tracker=?, auto_login=?, ultra_iv=?, ultra_quests=? WHERE name=?"; + var sql = ` + UPDATE config + SET name=?, backend_url=?, port=?, heartbeat_max_time=?, pokemon_max_time=?, raid_max_time=?, startup_lat=?, startup_lon=?, token=?, jitter_value=?, + max_warning_time_raid=?, encounter_delay=?, min_delay_logout=?, max_empty_gmo=?, max_failed_count=?, max_no_quest_count=?, logging_url=?, logging_port=?, + logging_tls=?, logging_tcp=?, account_manager=?, deploy_eggs=?, nearby_tracker=?, auto_login=?, ultra_iv=?, ultra_quests=?, is_default=? + WHERE name=?`; var args = [ this.name, this.backendUrl, @@ -119,6 +195,7 @@ class Config { this.autoLogin, this.ultraIV, this.ultraQuests, + this.isDefault, oldName ]; var result = await query(sql, args); diff --git a/models/device.js b/models/device.js index eeb379a..014d9ac 100644 --- a/models/device.js +++ b/models/device.js @@ -13,7 +13,10 @@ class Device { return devices; } static async getByName(uuid) { - var sql = "SELECT uuid, config, last_seen FROM device WHERE uuid = ?"; + var sql = ` + SELECT uuid, config, last_seen + FROM device + WHERE uuid = ?`; var args = [uuid]; var result = await query(sql, args); if (result && result.length > 0) { @@ -26,7 +29,9 @@ class Device { return null; } static async create(uuid, config = null, lastSeen = null) { - var sql = "INSERT INTO device (uuid, config, last_seen) VALUES (?, ?, ?)"; + var sql = ` + INSERT INTO device (uuid, config, last_seen) + VALUES (?, ?, ?)`; var args = [uuid, config, lastSeen]; var result = await query(sql, args); return result.affectedRows === 1; @@ -38,7 +43,10 @@ class Device { return result.affectedRows === 1; } async save() { - var sql = "UPDATE device SET config = ?, last_seen = ? WHERE uuid = ?"; + var sql = ` + UPDATE device + SET config = ?, last_seen = ? + WHERE uuid = ?`; var args = [this.config, this.lastSeen, this.uuid]; var result = await query(sql, args); return result.affectedRows === 1; diff --git a/models/log.js b/models/log.js index 7f8f0c3..f971133 100644 --- a/models/log.js +++ b/models/log.js @@ -13,7 +13,9 @@ class Log { return logs; } static async create(uuid, message) { - var sql = "INSERT INTO log (uuid, timestamp, message) VALUES (?, UNIX_TIMESTAMP(), ?)"; + var sql = ` + INSERT INTO log (uuid, timestamp, message) + VALUES (?, UNIX_TIMESTAMP(), ?)`; var args = [uuid, message]; var result = await query(sql, args); return result.affectedRows === 1; diff --git a/schema.sql b/schema.sql index ec72424..15e8d0c 100644 --- a/schema.sql +++ b/schema.sql @@ -24,7 +24,8 @@ CREATE TABLE IF NOT EXISTS `config` ( `nearby_tracker` tinyint(1) DEFAULT 1, `auto_login` tinyint(1) DEFAULT 1, `ultra_iv` tinyint(1) DEFAULT 1, - `ultra_quests` tinyint(1) DEFAULT 1 + `ultra_quests` tinyint(1) DEFAULT 1, + `is_default` tinyint(1) DEFAULT 0 ); CREATE TABLE IF NOT EXISTS `log` ( diff --git a/views/config-assign.mustache b/views/config-assign.mustache index f36433e..1faf850 100644 --- a/views/config-assign.mustache +++ b/views/config-assign.mustache @@ -25,8 +25,8 @@ \ No newline at end of file diff --git a/views/config-delete.mustache b/views/config-delete.mustache index b585d85..f647a57 100644 --- a/views/config-delete.mustache +++ b/views/config-delete.mustache @@ -21,7 +21,7 @@ \ No newline at end of file diff --git a/views/config-edit.mustache b/views/config-edit.mustache index 741af1d..a2c4451 100644 --- a/views/config-edit.mustache +++ b/views/config-edit.mustache @@ -114,6 +114,11 @@ + +