diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 2d13ec9d2..4938aaeaa 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -48,7 +48,6 @@ fi set -e if [[ ${ENVIRONMENT} == "test" ]]; then - echo "[thinx-entrypoint] Running in TEST MODE!" curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter chmod +x ./cc-test-reporter diff --git a/lib/router.auth.js b/lib/router.auth.js index 678b64cda..8f05a7c1d 100644 --- a/lib/router.auth.js +++ b/lib/router.auth.js @@ -206,6 +206,7 @@ module.exports = function (app) { console.log(`[OID:${user_data.owner}] [LOGIN_INVALID] Password mismatch.`); auditLogError(user_data.owner, "password_mismatch"); alog.log(req.session.owner, "Password mismatch."); + stored_response.status(401); Util.responder(stored_response, false, "password_mismatch"); } return true; diff --git a/lib/router.github.js b/lib/router.github.js index a26ed14c7..09c5ad3e6 100644 --- a/lib/router.github.js +++ b/lib/router.github.js @@ -15,34 +15,36 @@ const app_config = Globals.app_config(); var AuditLog = require("../lib/thinx/audit"); var alog = new AuditLog(); var User = require("../lib/thinx/owner"); var user = new User(); +const Util = require("./thinx/util"); + // // OAuth2 for GitHub // -var githubOAuth; - -if (typeof (process.env.GITHUB_CLIENT_SECRET) !== "undefined" && process.env.GITHUB_CLIENT_SECRET !== null) { - try { - let specs = { - githubClient: process.env.GITHUB_CLIENT_ID, - githubSecret: process.env.GITHUB_CLIENT_SECRET, - baseURL: github_ocfg.base_url, // should be rather gotten from global config! - loginURI: '/api/oauth/github', - callbackURI: '/api/oauth/github/callback', - scope: 'user' - }; - githubOAuth = require('./thinx/oauth-github.js')(specs); - } catch (e) { - console.log(`[debug] [oauth] [github] github_ocfg init error: ${e}`); - } -} - module.exports = function (app) { /* * OAuth 2 with GitHub */ + var githubOAuth; + + if (typeof (process.env.GITHUB_CLIENT_SECRET) !== "undefined" && process.env.GITHUB_CLIENT_SECRET !== null) { + try { + let specs = { + githubClient: process.env.GITHUB_CLIENT_ID, + githubSecret: process.env.GITHUB_CLIENT_SECRET, + baseURL: github_ocfg.base_url, // should be rather gotten from global config! + loginURI: '/api/oauth/github', + callbackURI: '/api/oauth/github/callback', + scope: 'user' + }; + githubOAuth = require('./thinx/oauth-github.js')(specs); + } catch (e) { + console.log(`[debug] [oauth] [github] github_ocfg init error: ${e}`); + } + } + function validateGithubUser(response, token, userWrapper) { let owner_id = userWrapper.owner; // must not be nil @@ -157,7 +159,22 @@ module.exports = function (app) { if (typeof (original_response) !== "undefined") original_response.end("test-ok"); }); - githubOAuth.on('token', (oauth_token_string/* , resp, _res, req */) => { + githubOAuth.on('token', (oauth_token_string, resp, /* _res, req */) => { + + if (!Util.isDefined(oauth_token_string)) { + console.log("[github] debug token event without token", { oauth_token_string }, resp); + original_response.redirect( + app_config.public_url + '/error.html?success=failed&title=Sorry&reason=Intruder%20alert.' + ); + + return; + } + + if (typeof (oauth_token_string) === "object") { + console.log("[github] oauth token response:", oauth_token_string); + original_response.status(401).end(); + return; + } let oauth_token_array = oauth_token_string.split("&"); let access_token = oauth_token_array[0].replace("access_token=", ""); @@ -166,6 +183,7 @@ module.exports = function (app) { if (typeof (access_token) === "undefined") { console.log("[debug] [github] [token] No token, exiting."); + original_response.status(401).end(); return; } @@ -263,16 +281,12 @@ module.exports = function (app) { // Callback service parsing the authorization token and asking for the access token app.get('/api/oauth/github/callback', function (req, res) { - + // save original response to callbacks in this code path... when callback is called, response is used to reply (except for error) secureGithubCallbacks(res, () => { - if (githubOAuth.callback === "function") { - githubOAuth.callback(req, res); - } else { - console.log("[warning] githubOAuth.callback(req, res); is not a function"); - res.status(401).end(); - } - }); // save original response to callbacks in this code path... when callback is called, response is used to reply - + githubOAuth.callback(req, res, (err) => { + console.log("[spec] GitHub OAuth result", err); + //res.end(); // why does not the res end? + }); + }); }); - }; \ No newline at end of file diff --git a/lib/router.google.js b/lib/router.google.js index c557da6fe..3cef3ecd7 100644 --- a/lib/router.google.js +++ b/lib/router.google.js @@ -46,7 +46,7 @@ module.exports = function (app) { */ function createUserWithGoogle(req, ores, odata, userWrapper, access_token) { - console.log("Creating new user..."); + console.log("[google] Creating new user..."); // No e-mail to validate. var will_require_activation = true; @@ -73,6 +73,7 @@ module.exports = function (app) { const ourl = app_config.public_url + "/auth.html?t=" + token + "&g=true"; // require GDPR consent console.log(ourl); + console.log("Redirecting to:", ourl); ores.redirect(ourl); }); } diff --git a/lib/router.user.js b/lib/router.user.js index 1b7c34dec..0744e5dd2 100644 --- a/lib/router.user.js +++ b/lib/router.user.js @@ -14,6 +14,7 @@ module.exports = function (app) { req.session.destroy((err) => { console.log(err); }); + res.status(401); Util.responder(res, success, message); } else { res.redirect(message.redirectURL); @@ -25,6 +26,7 @@ module.exports = function (app) { user.password_reset(req.query.owner, req.query.reset_key, (success, message) => { if (!success) { req.session.destroy((/*err*/) => { + res.status(401); Util.responder(res, success, message); }); } else { @@ -37,6 +39,7 @@ module.exports = function (app) { user.password_reset_init(req.body.email, (success, message) => { if (!success) { req.session.destroy(); + res.status(401); } console.log("[debug] password_reset_init", success, message); Util.responder(res, success, message); @@ -50,6 +53,7 @@ module.exports = function (app) { console.log(cid, "[debug] set_password callback", success, message); if (!success) { if (typeof (req.session) !== "undefined") req.session.destroy(); + res.status(401); } console.log(cid, "[debug] set_password respond with success, message", success, message); Util.responder(res, success, message); @@ -64,6 +68,7 @@ module.exports = function (app) { if (err) { let errString = err.toString(); console.log(`[OID:${owner}] Chat message failed with error ${errString}`); + res.status(400); } else { console.log(`[OID:${owner}] Chat message sent.`); } diff --git a/lib/thinx/builder.js b/lib/thinx/builder.js index 893af7589..b8a50c5ed 100644 --- a/lib/thinx/builder.js +++ b/lib/thinx/builder.js @@ -471,6 +471,67 @@ module.exports = class Builder { return true; } + generate_thinx_json(api_envs, device, api_key, commit_id, git_tag, XBUILD_PATH) { + + // Load template + var thinx_json = JSON.parse( + fs.readFileSync( + __dirname + "/../../builder.thinx.dist.json" + ) + ); + + if (typeof (api_envs) === "undefined" || api_envs === null) { + console.log("[builder] No env vars to apply..."); + api_envs = []; + } + + if (api_envs.count > 0) { + console.log("[builder] Applying environment vars..."); + for (var object in api_envs) { + var key = Object.keys(object)[0]; + console.log("Setting " + key + " to " + object[key]); + thinx_json[key] = object[key]; + } + } else { + console.log("[builder] No environment vars to apply..."); + } + + // Attach/replace with important data + thinx_json.THINX_ALIAS = device.alias; + thinx_json.THINX_API_KEY = api_key; // inferred from last_key_hash + + // Replace important data... + thinx_json.THINX_COMMIT_ID = commit_id.replace("\n", ""); + thinx_json.THINX_FIRMWARE_VERSION_SHORT = git_tag.replace("\n", ""); + + var REPO_NAME = XBUILD_PATH.replace(/^.*[\\\/]/, '').replace(".git", ""); + + thinx_json.THINX_FIRMWARE_VERSION = REPO_NAME + ":" + git_tag.replace("\n", ""); + thinx_json.THINX_APP_VERSION = thinx_json.THINX_FIRMWARE_VERSION; + + thinx_json.THINX_OWNER = device.owner; + thinx_json.THINX_PLATFORM = device.platform; + thinx_json.LANGUAGE_NAME = JSON2H.languageNameForPlatform(device.platform); + thinx_json.THINX_UDID = device.udid; + + // Attach/replace with more specific data..."); + thinx_json.THINX_CLOUD_URL = app_config.api_url.replace("https://", "").replace("http://", ""); + thinx_json.THINX_MQTT_URL = app_config.mqtt.server.replace("mqtt://", ""); // due to problem with slashes in json and some libs on platforms + thinx_json.THINX_AUTO_UPDATE = true; // device.autoUpdate + thinx_json.THINX_MQTT_PORT = app_config.mqtt.port; + thinx_json.THINX_API_PORT = app_config.port; + thinx_json.THINX_ENV_SSID = ""; + thinx_json.THINX_ENV_PASS = ""; + + if (typeof (app_config.secure_port) !== "undefined") { + thinx_json.THINX_API_PORT_SECURE = app_config.secure_port; + } + + thinx_json.THINX_AUTO_UPDATE = device.auto_update; + thinx_json.THINX_FORCED_UPDATE = false; + + return thinx_json; + } run_build(br, notifiers, callback, transmit_key) { @@ -710,27 +771,7 @@ module.exports = class Builder { console.log("[builder] REPO_VERSION (TAG+REV) [unused var]: '" + REPO_VERSION.replace(/\n/g, "") + "'"); - var header_file = null; - try { - console.log("Finding", HEADER_FILE_NAME, "in", XBUILD_PATH); - var h_file = finder.from(XBUILD_PATH).findFiles(HEADER_FILE_NAME); - if ((typeof (h_file) !== "undefined") && h_file !== null) { - header_file = h_file[0]; - } - console.log("[builder] found header_file: " + header_file); - } catch (e) { - console.log("Exception while getting header, use FINDER!: " + e); - blog.state(build_id, owner, udid, "error"); - } - - if (header_file === null) { - header_file = XBUILD_PATH / HEADER_FILE_NAME; - console.log("header_file empty, assigning path:", header_file); - } - - console.log("[builder] Final header_file:", header_file); - - var REPO_NAME = XBUILD_PATH.replace(/^.*[\\\/]/, '').replace(".git", ""); + // // Fetch API Envs and create header file @@ -743,63 +784,7 @@ module.exports = class Builder { // must not be blocking } - // --> extract from here - - // Load template - var thinx_json = JSON.parse( - fs.readFileSync( - __dirname + "/../../builder.thinx.dist.json" - ) - ); - - if (typeof (api_envs) === "undefined" || api_envs === null) { - console.log("[builder] No env vars to apply..."); - api_envs = []; - } - - if (api_envs.count > 0) { - console.log("[builder] Applying environment vars..."); - for (var object in api_envs) { - var key = Object.keys(object)[0]; - console.log("Setting " + key + " to " + object[key]); - thinx_json[key] = object[key]; - } - } else { - console.log("[builder] No environment vars to apply..."); - } - - // Attach/replace with important data - thinx_json.THINX_ALIAS = device.alias; - thinx_json.THINX_API_KEY = api_key; // inferred from last_key_hash - - // Replace important data... - thinx_json.THINX_COMMIT_ID = commit_id.replace("\n", ""); - thinx_json.THINX_FIRMWARE_VERSION_SHORT = git_tag.replace("\n", ""); - thinx_json.THINX_FIRMWARE_VERSION = REPO_NAME + ":" + git_tag.replace("\n", ""); - thinx_json.THINX_APP_VERSION = thinx_json.THINX_FIRMWARE_VERSION; - - thinx_json.THINX_OWNER = device.owner; - thinx_json.THINX_PLATFORM = device.platform; - thinx_json.LANGUAGE_NAME = JSON2H.languageNameForPlatform(device.platform); - thinx_json.THINX_UDID = udid; - - // Attach/replace with more specific data..."); - thinx_json.THINX_CLOUD_URL = app_config.api_url.replace("https://", "").replace("http://", ""); - thinx_json.THINX_MQTT_URL = app_config.mqtt.server.replace("mqtt://", ""); // due to problem with slashes in json and some libs on platforms - thinx_json.THINX_AUTO_UPDATE = true; // device.autoUpdate - thinx_json.THINX_MQTT_PORT = app_config.mqtt.port; - thinx_json.THINX_API_PORT = app_config.port; - thinx_json.THINX_ENV_SSID = ""; - thinx_json.THINX_ENV_PASS = ""; - - if (typeof (app_config.secure_port) !== "undefined") { - thinx_json.THINX_API_PORT_SECURE = app_config.secure_port; - } - - thinx_json.THINX_AUTO_UPDATE = device.auto_update; - thinx_json.THINX_FORCED_UPDATE = false; - - // <-- extract to here + let thinx_json = this.generate_thinx_json(api_envs, device, api_key, commit_id, git_tag, XBUILD_PATH); console.log("[builder] Writing template to thinx_build.json..."); @@ -815,6 +800,26 @@ module.exports = class Builder { return; } + var header_file = null; + try { + console.log("Finding", HEADER_FILE_NAME, "in", XBUILD_PATH); + var h_file = finder.from(XBUILD_PATH).findFiles(HEADER_FILE_NAME); + if ((typeof (h_file) !== "undefined") && h_file !== null) { + header_file = h_file[0]; + } + console.log("[builder] found header_file: " + header_file); + } catch (e) { + console.log("Exception while getting header, use FINDER!: " + e); + blog.state(build_id, owner, udid, "error"); + } + + if (header_file === null) { + header_file = XBUILD_PATH / HEADER_FILE_NAME; + console.log("header_file empty, assigning path:", header_file); + } + + console.log("[builder] Final header_file:", header_file); + if ((platform != "mongoose") || (platform != "python") || (platform != "nodejs")) { console.log("[builder] Generating C-headers from into", header_file); if (fs.existsSync(header_file)) { @@ -824,14 +829,14 @@ module.exports = class Builder { } } - // <--- cut until here as configureBuildForDevice(header_file, device, api_envs, api_key, git_tag, commit_id, REPO_NAME, udid, platform) - callback(true, { response: "build_started", build_id: build_id }); // last callback before executing - // start the build in background + // + // start the build in background (device, br, udid, build_id, owner, ROOT, fcid, git, sanitized_branch, XBUILD_PATH, api_envs...) + // var fcid = "000000"; if (typeof (device.fcid) !== "undefined") { diff --git a/lib/thinx/device.js b/lib/thinx/device.js index 698bf2c4c..a8400089a 100644 --- a/lib/thinx/device.js +++ b/lib/thinx/device.js @@ -6,7 +6,10 @@ var app_config = Globals.app_config(); var prefix = Globals.prefix(); var fs = require("fs-extra"); + +// deepcode ignore HttpToHttps: support legacy devices in Device API var http = require('http'); + var md5 = require('md5'); var debug_device = app_config.debug.device || true; @@ -294,147 +297,174 @@ module.exports = class Device { }); // atomic } - checkinExistingDevice(device, reg, api_key, res, callback) { + markUserBuildGoal(profile, device, res, callback) { - // Refresh MQTT credentials on successful registration (requires plugin-based authentication Redis/GoAuth) - this.authorize_mqtt(api_key, device); + var goals = profile.info.goals || []; + var changed = false; - owner.profile(device.owner, (status, profile) => { + if (!goals.includes('update')) { + goals.push('update'); + changed = true; + } - if (status === false) { - console.log("WARNING! Failed to fetch device owner profile in device checkin! Transformers will not work."); - } + if (!goals.includes('build')) { + goals.push('build'); + changed = true; + } - console.log("[OID:" + reg.owner + "] [DEVICE_CHECKIN] Checkin Existing device: " + JSON.stringify(reg.udid, null, 4)); - InfluxConnector.statsLog(reg.owner, "DEVICE_CHECKIN", reg.udid); - // Override/update last checkin timestamp - device.lastupdate = new Date(); + // allow final goal leading to full CI device management + if (changed) { + userlib.atomic("users", "edit", device.owner, { + "info": { + "goals": goals + } + }, (error, body) => { + if (error) { + console.log("ERR: " + error + " : " + JSON.stringify(body)); + alog.log(owner, "Profile update failed.", "error"); + callback(res, false, "update_failed"); + } else { + alog.log(device.owner, "Owner state updated.", "warning"); + callback(res, true, "updated"); + } + }); + } + } - var checkins = [device.lastupdate]; - if (typeof (device.checkins) === "undefined") { - device.checkins = checkins; - } else { - checkins = device.checkins.slice(-10); - checkins.push(device.lastupdate); - device.checkins = checkins.slice(-100); // store last 10 checkins only + updateDeviceDataWithRegistration(reg, device) { + + // -> updateDeviceCheckins + var checkins = [device.lastupdate]; + if (typeof (device.checkins) === "undefined") { + device.checkins = checkins; + } else { + checkins = device.checkins.slice(-10); + checkins.push(device.lastupdate); + device.checkins = checkins.slice(-100); // store last 10 checkins only + } + // <- updateDeviceCheckins + + // version from device overrides server + if (Util.isDefined(reg.version)) { + device.version = reg.version; + } + + // env_hash from device overrides server + if (Util.isDefined(reg.env_hash)) { + device.env_hash = reg.env_hash; + } + + // push from device overrides server + if (Util.isDefined(reg.push)) { + device.push = reg.push; + } + + // name from server overrides device + if (Util.isDefined(reg.alias)) { + if (!Util.isDefined(device.alias)) { + device.alias = reg.alias; } + } - // firmware from device overrides server - if (typeof (reg.firmware) !== "undefined" && reg.firmware !== null) { + // platform may change under same MCU + if (Util.isDefined(reg.platform)) { + device.platform = reg.platform; + } - var envelope = deploy.latestFirmwareEnvelope(device.owner, device.udid); + // + // Extended SigFox Support + // - if ((typeof (envelope) !== "undefined") && (typeof (envelope.firmware) !== "undefined")) { + // status, snr, rssi, station, lat, long + if (Util.isDefined(reg.status)) { + device.status = reg.status; + } - const reg_f_array = reg.firmware.split(":"); + if (Util.isDefined(reg.snr)) { + device.snr = reg.snr; + } else { + device.snr = null; + } - if (envelope.firmware.indexOf(reg_f_array[0]) == 0) { + if (Util.isDefined(reg.rssi)) { + device.rssi = reg.rssi; + } else { + device.rssi = null; + } - var goals = profile.info.goals || []; - var changed = false; + if (Util.isDefined(reg.station)) { + device.station = reg.station; + } else { + device.station = null; + } - if (!goals.includes('update')) { - goals.push('update'); - changed = true; - } + // Includes - if (!goals.includes('build')) { - goals.push('build'); - changed = true; - } + if (Util.isDefined(reg.lat)) { + device.lat = reg.lat; + } - // allow final goal leading to full CI device management - if (changed) { - userlib.atomic("users", "edit", device.owner, { - "info": { - "goals": goals - } - }, (error, body) => { - if (error) { - console.log("ERR: " + error + " : " + JSON.stringify(body)); - alog.log(owner, "Profile update failed.", "error"); - callback(res, false, "update_failed"); - } else { - alog.log(device.owner, "Owner state updated.", "warning"); - callback(res, true, "updated"); - } - }); - } - } - } - device.firmware = reg.firmware; - } + if (Util.isDefined(reg.lon)) { + device.lon = reg.lon; + } - // version from device overrides server - if (typeof (reg.version) !== "undefined" && reg.version !== null) { - device.version = reg.version; - } + // IV Compatibility - // env_hash from device overrides server - if (typeof (reg.env_hash) !== "undefined" && reg.env_hash !== null) { - device.env_hash = reg.env_hash; - } + /* Adds AES IV for devices that do not have one yet. */ + if (!Util.isDefined(device.iv)) { + device.iv = crypto.randomBytes(16).toString('base64'); + } - // push from device overrides server - if (typeof (reg.push) !== "undefined" && reg.push !== null) { - device.push = reg.push; - } + if (!Util.isDefined(device.aes_key)) { + device.aes_key = crypto.randomBytes(32).toString('base64'); + } - // name from server overrides device - if (typeof (reg.alias) !== "undefined" && reg.alias !== null) { - if (typeof (device.alias) === "undefined") { - device.alias = reg.alias; - } - } + // DevSec compatibility - // platform may change under same MCU - if (typeof (reg.platform) !== "undefined" && reg.platform !== null) { - device.platform = reg.platform; - } + if (Util.isDefined(reg.fcid)) { + device.fcid = reg.fcid; + } - // - // Extended SigFox Support - // + return device; + } - // status, snr, rssi, station, lat, long - if (typeof (reg.status) !== "undefined" && reg.status !== null) { - device.status = reg.status; - } + checkinExistingDevice(device, reg, api_key, res, callback) { - if (typeof (reg.snr) !== "undefined" && reg.snr !== null) { - device.snr = reg.snr; - } else { - device.snr = null; - } + // Refresh MQTT credentials on successful registration (requires plugin-based authentication Redis/GoAuth) + this.authorize_mqtt(api_key, device); - if (typeof (reg.rssi) !== "undefined" && reg.rssi !== null) { - device.rssi = reg.rssi; - } else { - device.rssi = null; - } + owner.profile(device.owner, (status, profile) => { - if (typeof (reg.station) !== "undefined" && reg.station !== null) { - device.station = reg.station; - } else { - device.station = null; + if (status === false) { + console.log("WARNING! Failed to fetch device owner profile in device checkin! Transformers will not work."); } - // Includes + console.log("[OID:" + reg.owner + "] [DEVICE_CHECKIN] Checkin Existing device: " + JSON.stringify(reg.udid, null, 4)); + InfluxConnector.statsLog(reg.owner, "DEVICE_CHECKIN", reg.udid); + // Override/update last checkin timestamp + device.lastupdate = new Date(); - if (typeof (reg.lat) !== "undefined" && reg.lat !== null) { - device.lat = reg.lat; - } + // firmware from device overrides server data + if (typeof (reg.firmware) !== "undefined" && reg.firmware !== null) { - if (typeof (reg.lon) !== "undefined" && reg.lon !== null) { - device.lon = reg.lon; + // validate firmware against latest firmware envelope + var envelope = deploy.latestFirmwareEnvelope(device.owner, device.udid); + + // mark build goal if success + if ((typeof (envelope) !== "undefined") && (typeof (envelope.firmware) !== "undefined")) { + const reg_f_array = reg.firmware.split(":"); + if (envelope.firmware.indexOf(reg_f_array[0]) == 0) { + this.markUserBuildGoal(profile, device, res, callback); + } + } + device.firmware = reg.firmware; } - // COPY B + device = this.updateDeviceDataWithRegistration(reg, device, callback); + + // Legacy SigFox Support // in case there is no status, this is an downlink request and should provide // response for this device - // - // - // if ((typeof (reg.ack) !== "undefined")) { console.log("This is a SigFox downlink request."); @@ -475,23 +505,6 @@ module.exports = class Device { callback(res, false, "udid_atomic_error"); } - // IV Compatibility - - /* Adds AES IV for devices that do not have one yet. */ - if ((typeof (device.iv) === "undefined") || (device.iv === null)) { - device.iv = crypto.randomBytes(16).toString('base64'); - } - - if ((typeof (device.aes_key) === "undefined") || (device.aes_key === null)) { - device.aes_key = crypto.randomBytes(32).toString('base64'); - } - - // DevSec compatibility - - if (typeof (reg.fcid) !== "undefined" && reg.fcid !== null) { - device.fcid = reg.fcid; - } - // Status Transformers this.runDeviceTransformers(profile, device, callback, reg, res); diff --git a/lib/thinx/messenger.js b/lib/thinx/messenger.js index 08f506045..83fce17e8 100644 --- a/lib/thinx/messenger.js +++ b/lib/thinx/messenger.js @@ -190,6 +190,7 @@ module.exports = class Messenger { message.topic = mqtt_topic; message.done = true; // user already responded; never notify again... this.client.set(nid, JSON.stringify(message), (err) => { + console.log("[debug] publishing nid message", message); if (err) { console.log("☣️ [error] " + err); } @@ -308,7 +309,7 @@ module.exports = class Messenger { } } - updateAndTransformDeviceStatus(oid, did, message) { + updateAndTransformDeviceStatus(oid, did, message, topic) { this.devicelib.get(did, (error, body) => { if (error) { console.log(error); @@ -325,9 +326,7 @@ module.exports = class Messenger { } }); - this.user.get(oid).catch(e => { - console.log("Transformers failed with", e); - }).then((profile) => { + this.user.profile(oid, (profile) => { device.runDeviceTransformers(profile, body, null, null, null); }); } @@ -434,6 +433,8 @@ module.exports = class Messenger { console.log("☣️ [error] Socket not ready."); } + + // Attach reply-to topic and store to Redis actionable.topic = topic; // reply-to actionable.done = false; // user did not respond yet @@ -461,6 +462,7 @@ module.exports = class Messenger { var nid_data = JSON.parse(json_keys); if (!err) { // NID transaction already exists, update data... + if (!Util.isDefined(nid_data)) nid_data = {}; nid_data.done = true; nid_data.response = notification_to.response; nid_data.response_type = notification_to.response_type; @@ -530,11 +532,11 @@ module.exports = class Messenger { this.mqttDeviceRegistration(topic, message, oid); // Update device status and run Transformers on it - this.updateAndTransformDeviceStatus(oid, did, message); + this.updateAndTransformDeviceStatus(oid, did, message, topic); // Process other well-known mesages // Match by message.status (should be optional) - this.processActionableMessages(message, oid, did, topic); + this. processActionableMessages(message, oid, did, topic); } postRandomQuote(quote, opt_callback) { @@ -560,14 +562,13 @@ module.exports = class Messenger { try { this.clients[owner] = mqtt.connect(app_config.mqtt.server, mqtt_options); } catch (e) { - callback(false, e); - return; + return callback(false, e); } if (typeof (this.clients[owner]) === "undefined") { console.log("DEVELOPER/TEST ERROR – MQTT CONNECT FAILED, probably invalid mock."); - callback(false, "mqtt_connect_failed"); - return; + return callback(false, "mqtt_connect_failed"); + } this.clients[owner].on("connect", (error) => { diff --git a/lib/thinx/oauth-github.js b/lib/thinx/oauth-github.js index 67891d546..b3f43900b 100644 --- a/lib/thinx/oauth-github.js +++ b/lib/thinx/oauth-github.js @@ -1,64 +1,71 @@ -const https = require('https'); +var request = require('request'); var events = require('events'); var url = require('url'); var crypto = require('crypto'); -module.exports = function (opts) { - if (!opts.callbackURI) opts.callbackURI = '/github/callback'; - if (!opts.loginURI) opts.loginURI = '/github/login'; - if (typeof opts.scope === 'undefined') opts.scope = 'user'; - var state = crypto.randomBytes(8).toString('hex'); - var urlObj = url.parse(opts.baseURL); - urlObj.pathname = url.resolve(urlObj.pathname, opts.callbackURI); - var redirectURI = url.format(urlObj); - var emitter = new events.EventEmitter(); +module.exports = function(opts) { + if (!opts.callbackURI) opts.callbackURI = '/github/callback'; + if (!opts.loginURI) opts.loginURI = '/github/login'; + if (typeof opts.scope === 'undefined') opts.scope = 'user'; + var state = crypto.randomBytes(8).toString('hex'); + var urlObj = url.parse(opts.baseURL); + urlObj.pathname = url.resolve(urlObj.pathname, opts.callbackURI); + var redirectURI = url.format(urlObj); + var emitter = new events.EventEmitter(); + + function addRoutes(router, loginCallback) { + // compatible with flatiron/director + router.get(opts.loginURI, login); + router.get(opts.callbackURI, callback); + if (!loginCallback) return; + emitter.on('error', function(token, err, resp, tokenResp, req) { + loginCallback(err, token, resp, tokenResp, req) + }); + emitter.on('token', function(token, resp, tokenResp, req) { + loginCallback(false, token, resp, tokenResp, req) + }); + } + + function login(req, resp) { + var u = 'https://github.com/login/oauth/authorize' + + '?client_id=' + opts.githubClient + + (opts.scope ? '&scope=' + opts.scope : '') + + '&redirect_uri=' + redirectURI + + '&state=' + state + ; + resp.statusCode = 302; + resp.setHeader('location', u); + resp.end(); + } - function login(req, resp) { - var u = 'https://github.com/login/oauth/authorize' + - '?client_id=' + process.env.GITHUB_CLIENT_ID + - (opts.scope ? '&scope=' + opts.scope : '') + - '&redirect_uri=' + redirectURI + - '&state=' + state; - resp.statusCode = 302; - resp.setHeader('location', u); - resp.end(); - } - - function callback(req, resp, cb) { - var query = url.parse(req.url, true).query; - var code = query.code; - var body = ""; - if (!code) return cb("missing oauth code in github oauth callback"); //return emitter.emit('error', { error: 'missing oauth code' }, resp); - var o = { - host: 'github.com', - port: 443, - path: '/login/oauth/access_token?code=' + code + '&state=' + state, - headers: { - 'Authorization': 'Basic ' + new Buffer(process.env.GITHUB_CLIENT_ID + ':' + process.env.GITHUB_CLIENT_SECRET).toString('base64') - } - }; - https.get(o, (res) => { - res.setEncoding('utf8'); - res.on('data', (d) => { - body += d; - }); - res.on('end', () => { - if (cb) { - cb(null, body); - } - emitter.emit('token', body, resp, res, req); - }); - }).on('error', (e) => { - console.error(e); - if (cb) { - e.body = body; - return cb(e); - } - return emitter.emit('error', body, e, resp, req); - }); - } - - emitter.login = login; - emitter.callback = callback; - return emitter; -}; \ No newline at end of file + function callback(req, resp, cb) { + var query = url.parse(req.url, true).query + var code = query.code + if (!code) return emitter.emit('error', {error: 'missing oauth code'}, resp) + var u = 'https://github.com/login/oauth/access_token' + + '?client_id=' + opts.githubClient + + '&client_secret=' + opts.githubSecret + + '&code=' + code + + '&state=' + state + ; + request.get({url:u, json: true}, function (err, tokenResp, body) { + if (err) { + if (cb) { + err.body = body; + err.tokenResp = tokenResp; + return cb(err); + } + return emitter.emit('error', body, err, resp, tokenResp, req); + } + if (cb) { + cb(null, body); + } + emitter.emit('token', body, resp, tokenResp, req); + }); + } + + emitter.login = login; + emitter.callback = callback; + emitter.addRoutes = addRoutes; + return emitter; +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 82424303a..7c3e6a996 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4961,6 +4961,22 @@ "node": ">= 0.6.0" } }, + "node_modules/findup-sync/node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/fined": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", @@ -5674,6 +5690,15 @@ "grunt": "*" } }, + "node_modules/grunt-karma-coveralls/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/grunt-karma-coveralls/node_modules/ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -5938,6 +5963,18 @@ "node": ">= 4" } }, + "node_modules/grunt-karma-coveralls/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/grunt-karma-coveralls/node_modules/supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -6183,6 +6220,15 @@ "node": ">=0.10.0" } }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -7626,6 +7672,12 @@ "he": "bin/he" } }, + "node_modules/jacoco-parse/node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, "node_modules/jacoco-parse/node_modules/mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -8791,6 +8843,15 @@ "node": ">=0.10.0" } }, + "node_modules/meow/node_modules/trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -14640,18 +14701,6 @@ "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=", "optional": true }, - "node_modules/trim-newlines": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", - "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", @@ -15754,20 +15803,19 @@ "integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==", "dev": true, "requires": { - "ajv": "6.12.3", + "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.3.1", "globals": "^13.9.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "3.14.0", - "minimatch": "3.0.4", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, "dependencies": { "ajv": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "version": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", "dev": true, "requires": { @@ -15787,8 +15835,7 @@ } }, "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", "dev": true, "requires": { @@ -16110,7 +16157,7 @@ "requires": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "3.0.4" + "minimatch": "^3.0.4" }, "dependencies": { "debug": { @@ -16145,7 +16192,7 @@ "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", - "js-yaml": "3.14.0", + "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" }, "dependencies": { @@ -16909,7 +16956,7 @@ "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "requires": { - "lodash": "4.17.21" + "lodash": "^4.17.14" } }, "async-limiter": { @@ -17135,7 +17182,7 @@ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "optional": true, "requires": { - "minimist": "1.2.6" + "minimist": "^1.2.6" } }, "ms": { @@ -17208,7 +17255,7 @@ "resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz", "integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==", "requires": { - "hoek": "6.1.3" + "hoek": "6.x.x" } }, "bourne": { @@ -17465,7 +17512,7 @@ "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", "requires": { "exit": "0.1.2", - "glob": "7.1.7" + "glob": "^7.1.1" } }, "cliui": { @@ -17474,8 +17521,8 @@ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "devOptional": true, "requires": { - "string-width": "4.2.3", - "strip-ansi": "6.0.1", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, @@ -17685,7 +17732,7 @@ "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", "requires": { "leven": "^2.1.0", - "minimist": "1.2.6" + "minimist": "^1.1.0" } }, "commondir": { @@ -17730,7 +17777,7 @@ "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", "optional": true, "requires": { - "dot-prop": "5.1.1", + "dot-prop": "^5.2.0", "graceful-fs": "^4.1.2", "make-dir": "^3.0.0", "unique-string": "^2.0.0", @@ -17739,8 +17786,7 @@ }, "dependencies": { "dot-prop": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.1.1.tgz", + "version": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.1.1.tgz", "integrity": "sha512-QCHI6Lkf+9fJMpwfAFsTvbiSh6ujoPmhCLiDvD/n4dGtLvHfhuBwPdN6z2x4YSOwwtTcLoO/LP70xELWGF/JVA==", "optional": true, "requires": { @@ -19182,8 +19228,8 @@ "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", "dev": true, "requires": { - "glob": "7.1.7", - "minimatch": "3.0.4" + "glob": "^7.0.3", + "minimatch": "^3.0.3" } }, "fill-range": { @@ -19245,7 +19291,22 @@ "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", "dev": true, "requires": { - "glob": "7.1.7" + "glob": "~5.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } } }, "fined": { @@ -19452,8 +19513,8 @@ "has-unicode": "^2.0.1", "object-assign": "^4.1.1", "signal-exit": "^3.0.0", - "string-width": "4.2.3", - "strip-ansi": "6.0.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", "wide-align": "^1.1.2" } }, @@ -19593,7 +19654,7 @@ "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "3.0.4", + "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } @@ -19789,6 +19850,12 @@ "log-driver": "^1.2" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -19822,7 +19889,7 @@ "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", - "strip-ansi": "6.0.1", + "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, @@ -19885,7 +19952,7 @@ "dev": true, "requires": { "assert-plus": "^0.2.0", - "jsprim": "1.4.2", + "jsprim": "^1.2.2", "sshpk": "^1.7.0" } }, @@ -19989,6 +20056,15 @@ "uuid": "^3.0.0" } }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -20106,7 +20182,7 @@ "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "requires": { - "minimist": "1.2.6", + "minimist": "^1.2.5", "neo-async": "^2.6.0", "source-map": "^0.6.1", "uglify-js": "^3.1.4", @@ -20123,7 +20199,7 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "requires": { - "ajv": "6.12.3", + "ajv": "^6.12.3", "har-schema": "^2.0.0" }, "dependencies": { @@ -20154,7 +20230,15 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "5.0.1" + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, "has-bigints": { @@ -20264,7 +20348,7 @@ "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", "requires": { - "glob": "7.1.7", + "glob": "^7.1.6", "readable-stream": "^3.6.0" } }, @@ -21239,13 +21323,19 @@ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { - "minimist": "1.2.6" + "minimist": "0.0.8" } }, "mocha": { @@ -22164,12 +22254,20 @@ "decamelize": "^1.1.2", "loud-rejection": "^1.0.0", "map-obj": "^1.0.1", - "minimist": "1.2.6", + "minimist": "^1.1.3", "normalize-package-data": "^2.3.4", "object-assign": "^4.0.1", "read-pkg-up": "^1.0.1", "redent": "^1.0.0", - "trim-newlines": "4.0.2" + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + } } }, "merge-descriptors": { @@ -23212,14 +23310,14 @@ "version": "4.0.0", "bundled": true, "requires": { - "ansi-regex": "5.0.1", + "ansi-regex": "^5.0.1", "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.1", "signal-exit": "^3.0.0", - "string-width": "4.2.3", - "strip-ansi": "6.0.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", "wide-align": "^1.1.2" }, "dependencies": { @@ -23237,14 +23335,14 @@ "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "6.0.1" + "strip-ansi": "^6.0.1" } }, "strip-ansi": { "version": "6.0.1", "bundled": true, "requires": { - "ansi-regex": "5.0.1" + "ansi-regex": "^5.0.1" } } } @@ -23327,7 +23425,7 @@ "version": "4.0.1", "bundled": true, "requires": { - "minimatch": "3.0.4" + "minimatch": "^3.0.4" } }, "imurmurhash": { @@ -23690,8 +23788,8 @@ "has-unicode": "^2.0.0", "object-assign": "^4.1.0", "signal-exit": "^3.0.0", - "string-width": "4.2.3", - "strip-ansi": "6.0.1", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" } }, @@ -23718,7 +23816,7 @@ "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "6.0.1" + "strip-ansi": "^3.0.0" } } } @@ -23778,7 +23876,7 @@ "version": "3.0.0", "bundled": true, "requires": { - "glob": "7.1.7", + "glob": "^7.1.6", "ignore-walk": "^4.0.1", "npm-bundled": "^1.1.1", "npm-normalize-package-bin": "^1.0.1" @@ -24083,7 +24181,7 @@ "bundled": true, "requires": { "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "6.0.1" + "strip-ansi": "^4.0.0" }, "dependencies": { "ansi-regex": { @@ -24094,7 +24192,7 @@ "version": "4.0.0", "bundled": true, "requires": { - "ansi-regex": "5.0.1" + "ansi-regex": "^3.0.0" } } } @@ -24203,7 +24301,7 @@ "version": "1.1.3", "bundled": true, "requires": { - "string-width": "4.2.3" + "string-width": "^1.0.2 || 2" } }, "wrappy": { @@ -24317,8 +24415,8 @@ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "requires": { - "string-width": "4.2.3", - "strip-ansi": "6.0.1", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, @@ -24390,8 +24488,8 @@ "dev": true, "requires": { "ansi-styles": "^4.0.0", - "string-width": "4.2.3", - "strip-ansi": "6.0.1" + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, "y18n": { @@ -25902,7 +26000,7 @@ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "optional": true, "requires": { - "minimist": "1.2.6" + "minimist": "^1.2.6" } }, "tar": { @@ -26503,12 +26601,6 @@ "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=", "optional": true }, - "trim-newlines": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.0.2.tgz", - "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", - "dev": true - }, "tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", @@ -26881,7 +26973,7 @@ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "requires": { - "string-width": "4.2.3" + "string-width": "^1.0.2 || 2 || 3 || 4" } }, "wildcard": { @@ -26933,8 +27025,8 @@ "devOptional": true, "requires": { "ansi-styles": "^4.0.0", - "string-width": "4.2.3", - "strip-ansi": "6.0.1" + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, "wrappy": { diff --git a/services/console b/services/console index cdb7fad03..04ef169be 160000 --- a/services/console +++ b/services/console @@ -1 +1 @@ -Subproject commit cdb7fad03c53d95abbc6afd5e2ca4d86bd86e125 +Subproject commit 04ef169be19d7392a34b2775dc54ce07c875fae5 diff --git a/spec/jasmine/GDPRSpec.js b/spec/jasmine/GDPRSpec.js index 1f83d17a3..7d0775fd5 100644 --- a/spec/jasmine/GDPRSpec.js +++ b/spec/jasmine/GDPRSpec.js @@ -29,7 +29,7 @@ describe("GDPR", function () { it("should not fail while purging", function (done) { let gdpr = new GDPR(); gdpr.purgeOldUsers((result) => { - console.log("[spec] while purging", result); + expect(result).to.equal(true); done(); }); }, 10000); @@ -37,7 +37,7 @@ describe("GDPR", function () { it("should not fail while notifying", function (done) { let gdpr = new GDPR(); gdpr.notifyOldUsers((result) => { - console.log("[spec] while notifying", result); + expect(result).to.equal(true); done(); }); }, 10000); @@ -51,7 +51,6 @@ describe("GDPR", function () { let user = mock_user; user.last_update = d1; let gdpr = new GDPR(); - console.log("[spec] 3 months - 24 hours before deletion"); gdpr.notify24(user, (error) => { if (error) console.log("[spec] 24 hours before deletion ERROR:", error); done(); @@ -66,7 +65,6 @@ describe("GDPR", function () { d2.setHours(0, 0, 0, 0); let user = mock_user; user.last_update = d2; - console.log("[spec] 168 hours before deletion"); gdpr.notify168(user, (error) => { if (error) console.log("[spec] 168 hours before deletion ERROR", error); done(); diff --git a/spec/jasmine/MessengerSpec.js b/spec/jasmine/MessengerSpec.js index 290f18c9c..c2f143a15 100644 --- a/spec/jasmine/MessengerSpec.js +++ b/spec/jasmine/MessengerSpec.js @@ -140,12 +140,61 @@ describe("Messenger", function() { messenger.messageResponder(topic, message); }); - it("should be able to respond to specific message", function() { - let topic = "/owner/device/test"; - let message = "Bare no-NID message"; + it("should be able to process status connected message", function() { + let topic = "/07cef9718edaad79b3974251bb5ef4aedca58703142e8c4c48c20f96cda4979c/d6ff2bb0-df34-11e7-b351-eb37822aa172/status"; + let message = { + status: "connected" + }; + messenger.messageResponder(topic, message); + }); + + it("should be able to process status disconnected message", function() { + let topic = "/07cef9718edaad79b3974251bb5ef4aedca58703142e8c4c48c20f96cda4979c/d6ff2bb0-df34-11e7-b351-eb37822aa172/status"; + let message = { + status: "disconnected" + }; messenger.messageResponder(topic, message); }); + it("should be able to process connection message", function() { + let topic = "/07cef9718edaad79b3974251bb5ef4aedca58703142e8c4c48c20f96cda4979c/d6ff2bb0-df34-11e7-b351-eb37822aa172/status"; + let message = { + connected: true + }; + messenger.messageResponder(topic, message); + }); + + it("should be able to process disconnection message", function() { + let topic = "/07cef9718edaad79b3974251bb5ef4aedca58703142e8c4c48c20f96cda4979c/d6ff2bb0-df34-11e7-b351-eb37822aa172/status"; + let message = { + connected: false + }; + messenger.messageResponder(topic, message); + }); + + it("should be able to process actionable notification", function() { + let topic = "/07cef9718edaad79b3974251bb5ef4aedca58703142e8c4c48c20f96cda4979c/d6ff2bb0-df34-11e7-b351-eb37822aa172/status"; + let message = { + notification: { + response: false, + nid: "nid-0000" + } + }; + messenger.messageResponder(topic, message); +}); + + it("should be able to process actionable notification from device", function() { + let topic = "/07cef9718edaad79b3974251bb5ef4aedca58703142e8c4c48c20f96cda4979c/d6ff2bb0-df34-11e7-b351-eb37822aa172/status"; + let message = { + notification: { + response: true, + body: "Notification Response", + response_type: "string" + } + }; + messenger.messageResponder(topic, message); + }); + // message_callback(...) it("should be able to survive message_callback call", function() { messenger.message_callback("/owner/device/test", "Bare no-NID message"); diff --git a/spec/jasmine/ZZ-AppSessionUserSpec.js b/spec/jasmine/ZZ-AppSessionUserSpec.js index 001d22e42..879e9f2c6 100644 --- a/spec/jasmine/ZZ-AppSessionUserSpec.js +++ b/spec/jasmine/ZZ-AppSessionUserSpec.js @@ -141,7 +141,7 @@ describe("User Routes", function () { chai.request(thx.app) .get('/api/user/activate') .end((_err, res) => { - expect(res.status).to.equal(200); + expect(res.status).to.equal(401); expect(res.text).to.equal('{"success":false,"response":"activation_key_missing"}'); done(); }); @@ -174,7 +174,7 @@ describe("User Routes", function () { .post('/api/user/password/reset') .send({}) .end((_err, res) => { - expect(res.status).to.equal(200); + expect(res.status).to.equal(401); expect(res.text).to.be.a('string'); expect(res.text).to.equal('{"success":false,"response":"email_not_found"}'); done(); @@ -201,7 +201,7 @@ describe("User Routes", function () { chai.request(thx.app) .get('/api/user/password/reset') .end((_err, res) => { - expect(res.status).to.equal(200); + expect(res.status).to.equal(401); expect(res.text).to.be.a('string'); expect(res.text).to.equal('{"success":false,"response":"missing_reset_key"}'); done(); @@ -212,7 +212,7 @@ describe("User Routes", function () { chai.request(thx.app) .get('/api/user/password/reset?reset_key=invalid') .end((_err, res) => { - expect(res.status).to.equal(200); + expect(res.status).to.equal(401); expect(res.text).to.be.a('string'); expect(res.text).to.equal('{"success":false,"response":"user_not_found"}'); // because this is nov calid reset_key done(); @@ -223,7 +223,7 @@ describe("User Routes", function () { chai.request(thx.app) .get('/api/user/password/reset?reset_key=invalid?owner=' + envi.dynamic.owner) .end((_err, res) => { - expect(res.status).to.equal(200); + expect(res.status).to.equal(401); expect(res.text).to.be.a('string'); expect(res.text).to.equal('{"success":false,"response":"user_not_found"}'); // because this is nov calid reset_key generated by posting valid e-mail to password reset done(); @@ -246,7 +246,7 @@ describe("User Routes", function () { .post('/api/user/password/set') .send({}) .end((_err, res) => { - expect(res.status).to.equal(200); + expect(res.status).to.equal(401); expect(res.text).to.be.a('string'); expect(res.text).to.equal('{"success":false,"response":"password_mismatch"}'); done(); @@ -259,7 +259,7 @@ describe("User Routes", function () { .post('/api/user/password/set') .send({ password: "A", rpassword: "B" }) .end((_err, res) => { - expect(res.status).to.equal(200); + expect(res.status).to.equal(401); expect(res.text).to.be.a('string'); expect(res.text).to.equal('{"success":false,"response":"password_mismatch"}'); done(); @@ -713,7 +713,7 @@ describe("User Routes", function () { .send({}) .end((_err, res) => { console.log("🚸 [chai] POST /api/user/chat response:", res.text, " status:", res.status); - expect(res.status).to.equal(200); + expect(res.status).to.equal(400); //expect(res.text).to.be.a('string'); done(); }); diff --git a/spec/jasmine/ZZ-AppSessionUserV2DeleteSpec.js b/spec/jasmine/ZZ-AppSessionUserV2DeleteSpec.js index 6bb4047dd..bfb592f41 100644 --- a/spec/jasmine/ZZ-AppSessionUserV2DeleteSpec.js +++ b/spec/jasmine/ZZ-AppSessionUserV2DeleteSpec.js @@ -183,7 +183,7 @@ describe("User Routes V2", function () { .send({ username: "dynamic2", password: "dynamic3" }) .end((_err1, res1) => { console.log("🚸 [chai] POST /api/login response:", res1.text, "status", res1.status); - expect(res1.status).to.equal(200); + expect(res1.status).to.equal(401); expect(res1.text).to.equal('{"success":false,"response":"password_mismatch"}'); done(); }); @@ -208,7 +208,7 @@ describe("User Routes V2", function () { .send({}) .end((_err, res) => { console.log("🚸 [chai] V2 POST /api/v2/chat response:", res.text, " status:", res.status); - expect(res.status).to.equal(200); + expect(res.status).to.equal(400); //expect(res.text).to.be.a('string'); done(); }); diff --git a/spec/jasmine/ZZ-RouterOAuthSpec.js b/spec/jasmine/ZZ-RouterOAuthSpec.js index 6c197b7e8..54294aa3d 100644 --- a/spec/jasmine/ZZ-RouterOAuthSpec.js +++ b/spec/jasmine/ZZ-RouterOAuthSpec.js @@ -61,7 +61,7 @@ describe("OAuth", function () { .get('/api/oauth/github/callback') .end((err, res) => { console.log("🚸 [chai] response /api/oauth/github/callback status:", res.status); - expect(res.status).to.equal(401); // only in test now because of unset event listeners! + expect(res.status).to.equal(200); done(); }); }, 30000); @@ -70,7 +70,7 @@ describe("OAuth", function () { chai.request(thx.app) .get('/api/oauth/github/callback?code=B') .end((err, res) => { - expect(res.status).to.equal(401); // only in test now because of unset event listeners! + expect(res.status).to.equal(401); done(); }); }, 30000);