UNPKG

node-red-contrib-snap4city-user

Version:

Nodes for Snap4city project, targeted to standard user (no developer)

183 lines (170 loc) 10.4 kB
/* NODE-RED-CONTRIB-SNAP4CITY-USER Copyright (C) 2018 DISIT Lab http://www.disit.org - University of Florence This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ module.exports = function (RED) { function Snap4cityAuthentication(config) { RED.nodes.createNode(this, config); var node = this; node.name = config.name; node.domain = config.domain; node.domainLight = config.domain.replace("https://", "").replace("http://", "").replace("/", ""); node.isMainAccount = config.ismainaccount; var s4cUtility = require("./snap4city-utility.js"); const logger = s4cUtility.getLogger(RED, node); node.s4cAuth = this; this.setNewOwnership = function (accessToken, uid) { var os = require('os'); var homedir = os.homedir() + "/"; var fs = require('fs'); logger.info("Try to set new ownership on " + node.domain); if (!fs.existsSync(__dirname + "/../node-red-contrib-snap4city-developer/config/ownership_" + node.domainLight) && !fs.existsSync(__dirname + "/../node-red-contrib-snap4city-user/config/ownership_" + node.domainLight) && !fs.existsSync(__dirname + "/../../../.snap4cityConfig/ownership_" + node.domainLight) && !fs.existsSync(homedir + ".snap4cityConfig/ownership_" + node.domainLight)) { var ifaces = os.networkInterfaces(); var url = s4cUtility.settingUrl(RED,node, "ownershipUrl", "https://www.snap4city.org", "/ownership-api/v1/") + "register/"; var params = "?accessToken=" + accessToken; var iplocal = null; Object.keys(ifaces).forEach(function (ifname) { ifaces[ifname].forEach(function (iface) { if ('IPv4' !== iface.family || iface.internal !== false) { // skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses return; } if (iface.address.indexOf("192.168") != -1) { iplocal = iface.address; return; } }); }); var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; var xmlHttp = new XMLHttpRequest(); logger.info(encodeURI(url)); xmlHttp.open("POST", encodeURI(url + params), false); xmlHttp.setRequestHeader("Content-Type", "application/json"); var message = { elementId: uid, elementType: "AppID", elementName: new Date().toJSON().slice(0, 16), elementUrl: "http://" + iplocal + ":" + RED.settings.uiPort, elementDetails: { edgegateway_type: os.platform() + "_" + os.type() + "_" + os.release() } }; xmlHttp.send(JSON.stringify(message)); if (xmlHttp.responseText != "") { try { response = JSON.parse(xmlHttp.responseText) logger.info("ResponseText: " + xmlHttp.responseText + " status: " + xmlHttp.status); if (typeof response.error == "undefined") { if (fs.existsSync(__dirname + "/../node-red-contrib-snap4city-user")) { if (!fs.existsSync(__dirname + "/../node-red-contrib-snap4city-user/config")) { fs.mkdirSync(__dirname + "/../node-red-contrib-snap4city-user/config"); } fs.writeFileSync(__dirname + "/../node-red-contrib-snap4city-user/config/ownership_" + node.domainLight, ""); } if (fs.existsSync(__dirname + "/../node-red-contrib-snap4city-developer")) { if (!fs.existsSync(__dirname + "/../node-red-contrib-snap4city-developer/config")) { fs.mkdirSync(__dirname + "/../node-red-contrib-snap4city-developer/config"); } fs.writeFileSync(__dirname + "/../node-red-contrib-snap4city-developer/config/ownership_" + node.domainLight, ""); } if (fs.existsSync(homedir + ".snap4cityConfig")) { if (!fs.existsSync(homedir + ".snap4cityConfig")) { fs.mkdirSync(homedir + ".snap4cityConfig"); } fs.writeFileSync(homedir + ".snap4cityConfig/ownership_" + node.domainLight, ""); } } } catch (e) {} } } else { if (fs.existsSync(__dirname + "/../node-red-contrib-snap4city-user/config/ownership_" + node.domainLight) || fs.existsSync(__dirname + "/../node-red-contrib-snap4city-developer/config/ownership_" + node.domainLight)) { if (!fs.existsSync(homedir + ".snap4cityConfig")) { fs.mkdirSync(homedir + ".snap4cityConfig"); } fs.writeFileSync(homedir + ".snap4cityConfig/ownership_" + node.domainLight, ""); } } } this.retrieveCurrentUser = function () { return node.credentials.user.toLowerCase(); } this.refreshTokenGetAccessToken = function (uid) { var s4cUtility = require("./snap4city-utility.js"); const logger = s4cUtility.getLogger(RED, node); var url = s4cUtility.settingUrl(RED,node, "keycloakBaseUri", "https://www.snap4city.org", "/auth/realms/master/") + "protocol/openid-connect/token/"; logger.info(url); var params = ""; var expiresTimestamp = node.credentials.expiresTimestamp; var refreshToken = node.credentials.refreshToken; console.log("Refresh Token: " + refreshToken); if (typeof refreshToken == "undefined" || typeof expiresTimestamp == "undefined" || new Date().getTime() > expiresTimestamp) { params = "client_id=" + (RED.settings.keycloakClientid ? RED.settings.keycloakClientid : "nodered-iotedge") + "&grant_type=password&username=" + node.credentials.user + "&password=" + encodeURIComponent(node.credentials.password); } else { params = "client_id=" + (RED.settings.keycloakClientid ? RED.settings.keycloakClientid : "nodered-iotedge") + "&grant_type=refresh_token&scope=openid profile&refresh_token=" + refreshToken; } var response = ""; var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; var xmlHttp = new XMLHttpRequest(); logger.info("Refresh token from:" + encodeURI(url)); xmlHttp.open("POST", encodeURI(url), false); xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlHttp.send(params); logger.info("xmlHttp.responseText: " + xmlHttp.responseText); if (xmlHttp.responseText != "") { try { response = JSON.parse(xmlHttp.responseText); if (response.access_token != null && uid != null) { if (typeof expiresTimestamp == "undefined") { if (node.isMainAccount) { this.setNewOwnership(response.access_token, uid); } } node.credentials.accessToken = response.access_token; } if (response.refresh_token != null) { node.credentials.refreshToken = response.refresh_token; } if (response.refresh_expires_in != null) { node.credentials.expiresTimestamp = (new Date().getTime()) + response.refresh_expires_in * 1000; } } catch (e) { logger.error("Problem Parsing this data: " + xmlHttp.responseText); } if (response != "") { if (response.access_token != null) { return [response.access_token,response.expires_in]; } else { return "response.access_token in refreshTokenGetAccessToken null"; } } } return response; } } RED.httpAdmin.post("/retrieveAccessTokenAuthentication/", RED.auth.needsPermission('snap4city-authentication.read'), function (req, res) { var s4cUtility = require("./snap4city-utility.js"); res.json({ "accessToken": s4cUtility.retrieveAccessToken(RED, RED.nodes.getNode(req.body.nodeId), req.body.authenticationNodeId, null), "username": s4cUtility.retrieveCurrentUser(RED, RED.nodes.getNode(req.body.nodeId), req.body.authenticationNodeId), "appId": s4cUtility.retrieveAppID(RED), }); }); RED.nodes.registerType("snap4city-authentication", Snap4cityAuthentication, { credentials: { user: { type: "text" }, password: { type: "password" } } }); }