UNPKG

cloud-red

Version:

Harnessing Serverless for your cloud integration needs

1,205 lines (1,123 loc) 1.49 MB
/** * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ /** * Trigger enabled/disabled events when element.prop("disabled",false/true) is * called. * Used by RED.popover to hide a popover when the trigger element is disabled * as a disabled element doesn't emit mouseleave */ jQuery.propHooks.disabled = { set: function (element, value) { if (element.disabled !== value) { element.disabled = value; if (value) { $(element).trigger('disabled'); } else { $(element).trigger('enabled'); } } } }; ;/** * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ var RED = (function() { function appendNodeConfig(nodeConfig,done) { done = done || function(){}; var m = /<!-- --- \[red-module:(\S+)\] --- -->/.exec(nodeConfig.trim()); var moduleId; if (m) { moduleId = m[1]; } else { moduleId = "unknown"; } try { var hasDeferred = false; var nodeConfigEls = $("<div>"+nodeConfig+"</div>"); var scripts = nodeConfigEls.find("script"); var scriptCount = scripts.length; scripts.each(function(i,el) { var srcUrl = $(el).attr('src'); if (srcUrl && !/^\s*(https?:|\/|\.)/.test(srcUrl)) { $(el).remove(); var newScript = document.createElement("script"); newScript.onload = function() { scriptCount--; if (scriptCount === 0) { $("body").append(nodeConfigEls); done() } } $('body').append(newScript); newScript.src = RED.settings.apiRootUrl+srcUrl; hasDeferred = true; } else { if (/\/ace.js$/.test(srcUrl) || /\/ext-language_tools.js$/.test(srcUrl)) { // Block any attempts to load ace.js from a CDN - this will // break the version of ace included in the editor. // At the time of commit, the contrib-python nodes did this. // This is a crude fix until the python nodes are fixed. console.warn("Blocked attempt to load",srcUrl,"by",moduleId) $(el).remove(); } scriptCount--; } }) if (!hasDeferred) { $("body").append(nodeConfigEls); done(); } } catch(err) { RED.notify(RED._("notification.errors.failedToAppendNode",{module:moduleId, error:err.toString()}),{ type: "error", timeout: 10000 }); console.log("["+moduleId+"] "+err.toString()); done(); } } function loadNodeList() { $.ajax({ headers: { "Accept":"application/json" }, cache: false, url: 'nodes', success: function(data) { RED.nodes.setNodeList(data); RED.i18n.loadNodeCatalogs(function() { loadIconList(loadNodes); }); } }); } function loadIconList(done) { $.ajax({ headers: { "Accept":"application/json" }, cache: false, url: 'icons', success: function(data) { RED.nodes.setIconSets(data); if (done) { done(); } } }); } function loadNodes() { $.ajax({ headers: { "Accept":"text/html" }, cache: false, url: 'nodes', success: function(data) { var configs = data.trim().split(/(?=<!-- --- \[red-module:\S+\] --- -->)/); var stepConfig = function() { if (configs.length === 0) { $("body").i18n(); $("#palette > .palette-spinner").hide(); $(".palette-scroll").removeClass("hide"); $("#palette-search").removeClass("hide"); loadFlows(function() { if (RED.settings.theme("projects.enabled",false)) { RED.projects.refresh(function(activeProject) { RED.sidebar.info.refresh() if (!activeProject) { // Projects enabled but no active project RED.menu.setDisabled('menu-item-projects-open',true); RED.menu.setDisabled('menu-item-projects-settings',true); if (activeProject === false) { // User previously decline the migration to projects. } else { // null/undefined RED.projects.showStartup(); } } completeLoad(); }); } else { // Projects disabled by the user RED.sidebar.info.refresh() completeLoad(); } }); } else { var config = configs.shift(); appendNodeConfig(config,stepConfig); } } stepConfig(); } }); } function loadFlows(done) { $.ajax({ headers: { "Accept":"application/json", }, cache: false, url: 'flows', success: function(nodes) { if (nodes) { var currentHash = window.location.hash; RED.nodes.version(nodes.rev); RED.nodes.import(nodes.flows); RED.nodes.dirty(false); RED.view.redraw(true); if (/^#flow\/.+$/.test(currentHash)) { RED.workspaces.show(currentHash.substring(6)); } } done(); } }); } function completeLoad() { var persistentNotifications = {}; RED.comms.subscribe("notification/#",function(topic,msg) { var parts = topic.split("/"); var notificationId = parts[1]; if (notificationId === "runtime-deploy") { // handled in ui/deploy.js return; } if (notificationId === "node") { // handled below return; } if (notificationId === "project-update") { RED.nodes.clear(); RED.history.clear(); RED.view.redraw(true); RED.projects.refresh(function() { loadFlows(function() { var project = RED.projects.getActiveProject(); var message = { "change-branch": RED._("notification.project.change-branch", {project: project.git.branches.local}), "merge-abort": RED._("notification.project.merge-abort"), "loaded": RED._("notification.project.loaded", {project: msg.project}), "updated": RED._("notification.project.updated", {project: msg.project}), "pull": RED._("notification.project.pull", {project: msg.project}), "revert": RED._("notification.project.revert", {project: msg.project}), "merge-complete": RED._("notification.project.merge-complete") }[msg.action]; RED.notify("<p>"+message+"</p>"); RED.sidebar.info.refresh() }); }); return; } if (msg.text) { msg.default = msg.text; var text = RED._(msg.text,msg); var options = { type: msg.type, fixed: msg.timeout === undefined, timeout: msg.timeout, id: notificationId } if (notificationId === "runtime-state") { if (msg.error === "safe-mode") { options.buttons = [ { text: RED._("common.label.close"), click: function() { persistentNotifications[notificationId].hideNotification(); } } ] } else if (msg.error === "missing-types") { text+="<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>"; if (!!RED.projects.getActiveProject()) { options.buttons = [ { text: RED._("notification.label.manage-project-dep"), click: function() { persistentNotifications[notificationId].hideNotification(); RED.projects.settings.show('deps'); } } ] // } else if (RED.settings.theme('palette.editable') !== false) { } else { options.buttons = [ { text: RED._("common.label.close"), click: function() { persistentNotifications[notificationId].hideNotification(); } } ] } } else if (msg.error === "credentials_load_failed") { if (RED.settings.theme("projects.enabled",false)) { // projects enabled if (RED.user.hasPermission("projects.write")) { options.buttons = [ { text: RED._("notification.project.setupCredentials"), click: function() { persistentNotifications[notificationId].hideNotification(); RED.projects.showCredentialsPrompt(); } } ] } } else { options.buttons = [ { text: RED._("common.label.close"), click: function() { persistentNotifications[notificationId].hideNotification(); } } ] } } else if (msg.error === "missing_flow_file") { if (RED.user.hasPermission("projects.write")) { options.buttons = [ { text: RED._("notification.project.setupProjectFiles"), click: function() { persistentNotifications[notificationId].hideNotification(); RED.projects.showFilesPrompt(); } } ] } } else if (msg.error === "missing_package_file") { if (RED.user.hasPermission("projects.write")) { options.buttons = [ { text: RED._("notification.project.setupProjectFiles"), click: function() { persistentNotifications[notificationId].hideNotification(); RED.projects.showFilesPrompt(); } } ] } } else if (msg.error === "project_empty") { if (RED.user.hasPermission("projects.write")) { options.buttons = [ { text: RED._("notification.project.no"), click: function() { persistentNotifications[notificationId].hideNotification(); } }, { text: RED._("notification.project.createDefault"), click: function() { persistentNotifications[notificationId].hideNotification(); RED.projects.createDefaultFileSet(); } } ] } } else if (msg.error === "git_merge_conflict") { RED.nodes.clear(); RED.sidebar.versionControl.refresh(true); if (RED.user.hasPermission("projects.write")) { options.buttons = [ { text: RED._("notification.project.mergeConflict"), click: function() { persistentNotifications[notificationId].hideNotification(); RED.sidebar.versionControl.showLocalChanges(); } } ] } } } if (!persistentNotifications.hasOwnProperty(notificationId)) { persistentNotifications[notificationId] = RED.notify(text,options); } else { persistentNotifications[notificationId].update(text,options); } } else if (persistentNotifications.hasOwnProperty(notificationId)) { persistentNotifications[notificationId].close(); delete persistentNotifications[notificationId]; } }); RED.comms.subscribe("status/#",function(topic,msg) { var parts = topic.split("/"); var node = RED.nodes.node(parts[1]); if (node) { if (msg.hasOwnProperty("text") && /^[a-zA-Z]/.test(msg.text)) { msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()}); } node.status = msg; node.dirty = true; RED.view.redraw(); } }); RED.comms.subscribe("notification/node/#",function(topic,msg) { var i,m; var typeList; var info; if (topic == "notification/node/added") { var addedTypes = []; msg.forEach(function(m) { var id = m.id; RED.nodes.addNodeSet(m); addedTypes = addedTypes.concat(m.types); RED.i18n.loadNodeCatalog(id, function() { $.get('nodes/'+id, function(data) { appendNodeConfig(data); }); }); }); if (addedTypes.length) { typeList = "<ul><li>"+addedTypes.join("</li><li>")+"</li></ul>"; RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success"); } loadIconList(); } else if (topic == "notification/node/removed") { for (i=0;i<msg.length;i++) { m = msg[i]; info = RED.nodes.removeNodeSet(m.id); if (info.added) { typeList = "<ul><li>"+m.types.join("</li><li>")+"</li></ul>"; RED.notify(RED._("palette.event.nodeRemoved", {count:m.types.length})+typeList,"success"); } } loadIconList(); } else if (topic == "notification/node/enabled") { if (msg.types) { info = RED.nodes.getNodeSet(msg.id); if (info.added) { RED.nodes.enableNodeSet(msg.id); typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success"); } else { $.get('nodes/'+msg.id, function(data) { appendNodeConfig(data); typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success"); }); } } } else if (topic == "notification/node/disabled") { if (msg.types) { RED.nodes.disableNodeSet(msg.id); typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; RED.notify(RED._("palette.event.nodeDisabled", {count:msg.types.length})+typeList,"success"); } } else if (topic == "notification/node/upgraded") { RED.notify(RED._("palette.event.nodeUpgraded", {module:msg.module,version:msg.version}),"success"); RED.nodes.registry.setModulePendingUpdated(msg.module,msg.version); } // Refresh flow library to ensure any examples are updated RED.library.loadFlowLibrary(); }); RED.comms.subscribe("event-log/#", function(topic,payload) { var id = topic.substring(9); RED.eventLog.log(id,payload); }); } function showAbout() { $.get('red/about', function(data) { var aboutHeader = '<div style="text-align:center;">'+ '<img width="50px" src="red/images/node-red-icon.svg" />'+ '</div>'; RED.sidebar.info.set(aboutHeader+marked(data)); RED.sidebar.info.show(); }); } function loadEditor() { var menuOptions = []; if (RED.settings.theme("projects.enabled",false)) { menuOptions.push({id:"menu-item-projects-menu",label:RED._("menu.label.projects"),options:[ {id:"menu-item-projects-new",label:RED._("menu.label.projects-new"),disabled:false,onselect:"core:new-project"}, {id:"menu-item-projects-open",label:RED._("menu.label.projects-open"),disabled:false,onselect:"core:open-project"}, {id:"menu-item-projects-settings",label:RED._("menu.label.projects-settings"),disabled:false,onselect:"core:show-project-settings"} ]}); } menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[ // {id:"menu-item-view-show-grid",setting:"view-show-grid",label:RED._("menu.label.view.showGrid"),toggle:true,onselect:"core:toggle-show-grid"}, // {id:"menu-item-view-snap-grid",setting:"view-snap-grid",label:RED._("menu.label.view.snapGrid"),toggle:true,onselect:"core:toggle-snap-grid"}, // {id:"menu-item-status",setting:"node-show-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:"core:toggle-status", selected: true}, //null, // {id:"menu-item-bidi",label:RED._("menu.label.view.textDir"),options:[ // {id:"menu-item-bidi-default",toggle:"text-direction",label:RED._("menu.label.view.defaultDir"),selected: true, onselect:function(s) { if(s){RED.text.bidi.setTextDirection("")}}}, // {id:"menu-item-bidi-ltr",toggle:"text-direction",label:RED._("menu.label.view.ltr"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("ltr")}}}, // {id:"menu-item-bidi-rtl",toggle:"text-direction",label:RED._("menu.label.view.rtl"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("rtl")}}}, // {id:"menu-item-bidi-auto",toggle:"text-direction",label:RED._("menu.label.view.auto"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("auto")}}} // ]}, // null, {id:"menu-item-palette",label:RED._("menu.label.palette.show"),toggle:true,onselect:"core:toggle-palette", selected: true}, {id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true}, {id:"menu-item-event-log",label:RED._("eventLog.title"),onselect:"core:show-event-log"}, null ]}); menuOptions.push(null); menuOptions.push({id:"menu-item-import",label:RED._("menu.label.import"),options:[ {id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:"core:show-import-dialog"}, {id:"menu-item-import-library",label:RED._("menu.label.library"),options:[]} ]}); menuOptions.push({id:"menu-item-export",label:RED._("menu.label.export"),options:[ {id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),onselect:"core:show-export-dialog"}, {id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:"core:library-export"} ]}); menuOptions.push(null); menuOptions.push({id:"menu-item-search",label:RED._("menu.label.search"),onselect:"core:search"}); menuOptions.push(null); menuOptions.push({id:"menu-item-config-nodes",label:RED._("menu.label.displayConfig"),onselect:"core:show-config-tab"}); menuOptions.push({id:"menu-item-workspace",label:RED._("menu.label.flows"),options:[ {id:"menu-item-workspace-add",label:RED._("menu.label.add"),onselect:"core:add-flow"}, {id:"menu-item-workspace-edit",label:RED._("menu.label.rename"),onselect:"core:edit-flow"}, {id:"menu-item-workspace-delete",label:RED._("menu.label.delete"),onselect:"core:remove-flow"} ]}); menuOptions.push({id:"menu-item-subflow",label:RED._("menu.label.subflows"), options: [ {id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:"core:create-subflow"}, {id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:"core:convert-to-subflow"}, ]}); menuOptions.push(null); if (RED.settings.theme('palette.editable') !== false) { menuOptions.push({id:"menu-item-edit-palette",label:RED._("menu.label.editPalette"),onselect:"core:manage-palette"}); menuOptions.push(null); } menuOptions.push({id:"menu-item-user-settings",label:RED._("menu.label.settings"),onselect:"core:show-user-settings"}); menuOptions.push(null); menuOptions.push({id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:"core:show-help"}); menuOptions.push({id:"menu-item-help", label: RED.settings.theme("menu.menu-item-help.label",RED._("menu.label.help")), href: RED.settings.theme("menu.menu-item-help.url","http://nodered.org/docs") }); menuOptions.push({id:"menu-item-node-red-version", label:"v"+RED.settings.version, onselect: "core:show-about" }); RED.view.init(); RED.userSettings.init(); RED.user.init(); RED.library.init(); RED.keyboard.init(); RED.palette.init(); RED.eventLog.init(); console.log('eventlog init'); if (RED.settings.theme('palette.editable') !== false) { RED.palette.editor.init(); } else { console.log("Palette editor disabled"); } RED.sidebar.init(); if (RED.settings.theme("projects.enabled",false)) { RED.projects.init(); } else { console.log("Projects disabled"); } RED.subflow.init(); RED.workspaces.init(); RED.clipboard.init(); RED.search.init(); RED.editor.init(); RED.diff.init(); RED.menu.init({id:"btn-sidemenu",options: menuOptions}); RED.deploy.init(RED.settings.theme("deployButton",null)); RED.notifications.init(); RED.actions.add("core:show-about", showAbout); RED.nodes.init(); RED.comms.connect(); //RED.comms.connectWS(); $("#main-container").show(); $(".header-toolbar").show(); loadNodeList(); } var initialised = false; function init(options) { if (initialised) { throw new Error("RED already initialised"); } initialised = true; ace.require("ace/ext/language_tools"); options = options || {}; options.apiRootUrl = options.apiRootUrl || ""; if (options.apiRootUrl && !/\/$/.test(options.apiRootUrl)) { options.apiRootUrl = options.apiRootUrl+"/"; } RED.i18n.init(options, function() { RED.settings.init(options, loadEditor); }) } return { init: init } })(); ;/** * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ RED.events = (function() { var handlers = {}; function on(evt,func) { handlers[evt] = handlers[evt]||[]; handlers[evt].push(func); } function off(evt,func) { var handler = handlers[evt]; if (handler) { for (var i=0;i<handler.length;i++) { if (handler[i] === func) { handler.splice(i,1); return; } } } } function emit(evt,arg) { if (handlers[evt]) { for (var i=0;i<handlers[evt].length;i++) { try { handlers[evt][i](arg); } catch(err) { console.log("RED.events.emit error: ["+evt+"] "+(err.toString())); console.log(err); } } } } return { on: on, off: off, emit: emit } })(); ;/** * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ RED.i18n = (function() { var apiRootUrl; return { init: function(options, done) { apiRootUrl = options.apiRootUrl||""; i18n.init({ resGetPath: apiRootUrl+'locales/__ns__?lng=__lng__', dynamicLoad: false, load:'current', ns: { namespaces: ["editor","node-red","jsonata","infotips"], defaultNs: "editor" }, fallbackLng: ['en-US'], useCookie: false, returnObjectTrees: true },function() { done(); }); RED["_"] = function() { var v = i18n.t.apply(null,arguments); if (typeof v === 'string') { return v; } else { return arguments[0]; } } }, loadNodeCatalog: function(namespace,done) { var languageList = i18n.functions.toLanguages(i18n.detectLanguage()); var toLoad = languageList.length; languageList.forEach(function(lang) { $.ajax({ headers: { "Accept":"application/json" }, cache: false, url: apiRootUrl+'nodes/'+namespace+'/messages?lng='+lang, success: function(data) { i18n.addResourceBundle(lang,namespace,data); toLoad--; if (toLoad === 0) { done(); } } }); }) }, loadNodeCatalogs: function(done) { var languageList = i18n.functions.toLanguages(i18n.detectLanguage()); var toLoad = languageList.length; languageList.forEach(function(lang) { $.ajax({ headers: { "Accept":"application/json" }, cache: false, url: apiRootUrl+'nodes/messages?lng='+lang, success: function(data) { var namespaces = Object.keys(data); namespaces.forEach(function(ns) { i18n.addResourceBundle(lang,ns,data[ns]); }); toLoad--; if (toLoad === 0) { done(); } } }); }) } } })(); ;/** * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ RED.settings = (function () { var loadedSettings = {}; var userSettings = {}; var settingsDirty = false; var pendingSave; var hasLocalStorage = function () { try { return 'localStorage' in window && window['localStorage'] !== null; } catch (e) { return false; } }; var set = function (key, value) { if (!hasLocalStorage()) { return; } if (key === "auth-tokens") { localStorage.setItem(key, JSON.stringify(value)); } else { userSettings[key] = value; saveUserSettings(); } }; /** * If the key is not set in the localStorage it returns <i>undefined</i> * Else return the JSON parsed value * @param key * @returns {*} */ var get = function (key) { if (!hasLocalStorage()) { return undefined; } if (key === "auth-tokens") { return JSON.parse(localStorage.getItem(key)); } else { return userSettings[key]; } }; var remove = function (key) { if (!hasLocalStorage()) { return; } if (key === "auth-tokens") { localStorage.removeItem(key); } else { delete userSettings[key]; saveUserSettings(); } }; var setProperties = function(data) { for (var prop in loadedSettings) { if (loadedSettings.hasOwnProperty(prop) && RED.settings.hasOwnProperty(prop)) { delete RED.settings[prop]; } } for (prop in data) { if (data.hasOwnProperty(prop)) { RED.settings[prop] = data[prop]; } } loadedSettings = data; }; var setUserSettings = function(data) { userSettings = data; } var init = function (options, done) { var accessTokenMatch = /[?&]access_token=(.*?)(?:$|&)/.exec(window.location.search); if (accessTokenMatch) { var accessToken = accessTokenMatch[1]; RED.settings.set("auth-tokens",{access_token: accessToken}); window.location.search = ""; } RED.settings.apiRootUrl = options.apiRootUrl; $.ajaxSetup({ beforeSend: function(jqXHR,settings) { // Only attach auth header for requests to relative paths if (!/^\s*(https?:|\/|\.)/.test(settings.url)) { if (options.apiRootUrl) { settings.url = options.apiRootUrl+settings.url; } var auth_tokens = RED.settings.get("auth-tokens"); if (auth_tokens) { jqXHR.setRequestHeader("Authorization","Bearer "+auth_tokens.access_token); } jqXHR.setRequestHeader("Node-RED-API-Version","v2"); } } }); load(done); } var load = function(done) { $.ajax({ headers: { "Accept": "application/json" }, dataType: "json", cache: false, url: 'settings', success: function (data) { setProperties(data); if (!RED.settings.user || RED.settings.user.anonymous) { RED.settings.remove("auth-tokens"); } console.log("Node-RED: " + data.version); loadUserSettings(done); }, error: function(jqXHR,textStatus,errorThrown) { if (jqXHR.status === 401) { if (/[?&]access_token=(.*?)(?:$|&)/.test(window.location.search)) { window.location.search = ""; } RED.user.login(function() { load(done); }); } else { console.log("Unexpected error loading settings:",jqXHR.status,textStatus); } } }); }; function loadUserSettings(done) { $.ajax({ headers: { "Accept": "application/json" }, dataType: "json", cache: false, url: 'settings/user', success: function (data) { setUserSettings(data); done(); }, error: function(jqXHR,textStatus,errorThrown) { console.log("Unexpected error loading user settings:",jqXHR.status,textStatus); } }); } var setEnvProfiles = function(data) { awsEnvProfiles = data; } function saveUserSettings() { if (RED.user.hasPermission("settings.write")) { if (pendingSave) { clearTimeout(pendingSave); } pendingSave = setTimeout(function() { pendingSave = null; $.ajax({ method: 'POST', contentType: 'application/json', url: 'settings/user', data: JSON.stringify(userSettings), success: function (data) { }, error: function(jqXHR,textStatus,errorThrown) { console.log("Unexpected error saving user settings:",jqXHR.status,textStatus); } }); },300); } } function getAWSEnvprofiles(done) { $.ajax({ headers: { "Accept": "application/json" }, dataType: "json", cache: false, url: 'settings/aws/creds', success: function (data) { setEnvProfiles(data); done(); }, error: function(jqXHR,textStatus,errorThrown) { console.log("Unexpected error loading user settings:",jqXHR.status,textStatus); } }); } function setAWSEnvprofiles() { if (RED.user.hasPermission("settings.write")) { if (pendingSave) { clearTimeout(pendingSave); } pendingSave = setTimeout(function() { pendingSave = null; $.ajax({ method: 'POST', contentType: 'application/json', url: 'settings/aws/creds', data: JSON.stringify(awsEnvProfileInput), success: function (data) { }, error: function(jqXHR,textStatus,errorThrown) { console.log("Unexpected error saving user settings:",jqXHR.status,textStatus); } }); },300); } } function theme(property,defaultValue) { if (!RED.settings.editorTheme) { return defaultValue; } var parts = property.split("."); var v = RED.settings.editorTheme; try { for (var i=0;i<parts.length;i++) { v = v[parts[i]]; } if (v === undefined) { return defaultValue; } return v; } catch(err) { return defaultValue; } } return { init: init, load: load, loadUserSettings: loadUserSettings, set: set, get: get, remove: remove, theme: theme, getAWSEnvprofiles: getAWSEnvprofiles, setAWSEnvprofiles: setAWSEnvprofiles } })(); ;/** * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ RED.user = (function() { function login(opts,done) { if (typeof opts == 'function') { done = opts; opts = {}; } var dialog = $('<div id="node-dialog-login" class="hide">'+ '<div style="display: inline-block;width: 250px; vertical-align: top; margin-right: 10px; margin-bottom: 20px;"><img id="node-dialog-login-image" src=""/></div>'+ '<div style="display: inline-block; width: 250px; vertical-align: bottom; margin-left: 10px; margin-bottom: 20px;">'+ '<form id="node-dialog-login-fields" class="form-horizontal" style="margin-bottom: 0px;"></form>'+ '</div>'+ '</div>'); dialog.dialog({ autoOpen: false, dialogClass: "ui-dialog-no-close", modal: true, closeOnEscape: !!opts.cancelable, width: 600, resizable: false, draggable: false }); $("#node-dialog-login-fields").empty(); $.ajax({ dataType: "json", url: "auth/login", success: function(data) { var i=0; if (data.type == "credentials") { for (;i<data.prompts.length;i++) { var field = data.prompts[i]; var row = $("<div/>",{class:"form-row"}); $('<label for="node-dialog-login-'+field.id+'">'+RED._(field.label)+':</label><br/>').appendTo(row); var input = $('<input style="width: 100%" id="node-dialog-login-'+field.id+'" type="'+field.type+'" tabIndex="'+(i+1)+'"/>').appendTo(row); if (i<data.prompts.length-1) { input.keypress( (function() { var r = row; return function(event) { if (event.keyCode == 13) { r.next("div").find("input").focus(); event.preventDefault(); } } })() ); } row.appendTo("#node-dialog-login-fields"); } $('<div class="form-row" style="text-align: right; margin-top: 10px;"><span id="node-dialog-login-failed" style="line-height: 2em;float:left;" class="hide">'+RED._("user.loginFailed")+'</span><img src="red/images/spin.svg" style="height: 30px; margin-right: 10px; " class="login-spinner hide"/>'+ (opts.cancelable?'<a href="#" id="node-dialog-login-cancel" style="margin-right: 20px;" tabIndex="'+(i+1)+'">'+RED._("common.label.cancel")+'</a>':'')+ '<input type="submit" id="node-dialog-login-submit" style="width: auto;" tabIndex="'+(i+2)+'" value="'+RED._("user.login")+'"></div>').appendTo("#node-dialog-login-fields"); $("#node-dialog-login-submit").button(); $("#node-dialog-login-fields").submit(function(event) { $("#node-dialog-login-submit").button("option","disabled",true); $("#node-dialog-login-failed").hide(); $(".login-spinner").show(); var body = { client_id: "node-red-editor", grant_type: "password", scope:"" } for (var i=0;i<data.prompts.length;i++) { var field = data.prompts[i]; body[field.id] = $("#node-dialog-login-"+field.id).val(); } $.ajax({ url:"auth/token", type: "POST", data: body }).done(function(data,textStatus,xhr) { RED.settings.set("auth-tokens",data); $("#node-dialog-login").dialog('destroy').remove(); if (opts.updateMenu) { updateUserMenu(); } done(); }).fail(function(jqXHR,textStatus,errorThrown) { RED.settings.remove("auth-tokens"); $("#node-dialog-login-failed").show(); }).always(function() { $("#node-dialog-login-submit").button("option","disabled",false); $(".login-spinner").hide(); }); event.preventDefault(); }); } else if (data.type == "strategy") { i = 0; for (;i<data.prompts.length;i++) { var field = data.prompts[i]; var row = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields"); var loginButton = $('<a href="#"></a>',{style: "padding: 10px"}).appendTo(row).click(function() { document.location = field.url; }); if (field.image) { $("<img>",{src:field.image}).appendTo(loginButton); } else if (field.label) { var label = $('<span></span>').text(field.label); if (field.icon) { $('<i></i>',{class: "fa fa-2x "+field.icon, style:"vertical-align: middle"}).appendTo(loginButton); label.css({ "verticalAlign":"middle", "marginLeft":"8px" }); } label.appendTo(loginButton); } loginButton.button(); } } if (opts.cancelable) { $("#node-dialog-login-cancel").button().click(function( event ) { $("#node-dialog-login").dialog('destroy').remove(); }); } var loginImageSrc = data.image || "red/images/node-red-256.png"; $("#node-dialog-login-image").load(function() { dialog.dialog("open"); }).attr("src",loginImageSrc); } }); } function logout() { var tokens = RED.settings.get("auth-tokens"); var token = tokens?tokens.access_token:""; $.ajax({ url: "auth/revoke", type: "POST", data: {token:token} }).done(function(data,textStatus,xhr) { RED.settings.remove("auth-tokens"); if (data && data.redirect) { document.location.href = data.redirect; } else { document.location.reload(true); } }).fail(function(jqXHR,textStatus,errorThrown) { if (jqXHR.status === 401) { document.location.reload(true); } else { console.log(textStatus); } }) } function updateUserMenu() { $("#btn-usermenu-submenu li").remove(); if (RED.settings.user.anonymous) { RED.menu.addItem("btn-usermenu",{ id:"usermenu-item-login", label:RED._("menu.label.login"), onselect: function() { RED.user.login({cancelable:true},function() { RED.settings.load(function() { RED.notify(RED._("user.loggedInAs",{name:RED.settings.user.username}),"success"); updateUserMenu(); RED.events.emit("login",RED.settings.user.username);