').appendTo(sshwarningRow);
$('
').appendTo(subrow).click(function(e) {
@@ -895,6 +904,8 @@ RED.projects = (function() {
$("#user-settings-gitconfig-add-key").click();
},500);
});
+ // -----------------------------------------------------
+
// // Secret - clone
// row = $('
').appendTo(container);
@@ -989,7 +1000,6 @@ RED.projects = (function() {
sendRequest({
url: "projects",
type: "POST",
- requireCleanWorkspace: true,
handleAuthFail: false,
responses: {
200: function(data) {
@@ -1006,17 +1016,22 @@ RED.projects = (function() {
projectRepoInput.addClass("input-error");
},
'git_auth_failed': function(error) {
+ $(".projects-dialog-screen-create-row-auth-error").show();
+
projectRepoUserInput.addClass("input-error");
projectRepoPasswordInput.addClass("input-error");
// getRepoAuthDetails(req);
projectRepoSSHKeySelect.addClass("input-error");
projectRepoPassphrase.addClass("input-error");
- console.log("git auth error",error);
},
'project_empty': function(error) {
// This is handled via a runtime notification.
dialog.dialog("close");
},
+ 'credentials_load_failed': function(error) {
+ // This is handled via a runtime notification.
+ dialog.dialog("close");
+ },
'unexpected_error': function(error) {
console.log("unexpected_error",error)
}
@@ -1396,14 +1411,9 @@ RED.projects = (function() {
-
- function sendRequest(options,body) {
- // dialogBody.hide();
- console.log(options.url,body);
-
- if (options.requireCleanWorkspace && RED.nodes.dirty()) {
- var message = 'You have undeployed changes that will be lost. Do you want to continue?';
- var alwaysCallback;
+ function requireCleanWorkspace(done) {
+ if (RED.nodes.dirty()) {
+ var message = '
You have undeployed changes that will be lost.
Do you want to continue?
';
var cleanNotification = RED.notify(message,{
type:"info",
fixed: true,
@@ -1415,29 +1425,57 @@ RED.projects = (function() {
text: RED._("common.label.cancel"),
click: function() {
cleanNotification.close();
- if (options.cancel) {
- options.cancel();
- }
- if (alwaysCallback) {
- alwaysCallback();
- }
+ done(true);
}
},{
text: 'Continue',
click: function() {
cleanNotification.close();
- delete options.requireCleanWorkspace;
- sendRequest(options,body).always(function() {
- if (alwaysCallback) {
- alwaysCallback();
- }
-
- })
+ done(false);
}
}
]
});
+
+ }
+ }
+
+ function sendRequest(options,body) {
+ // dialogBody.hide();
+ console.log(options.url,body);
+
+ if (options.requireCleanWorkspace && RED.nodes.dirty()) {
+ var thenCallback;
+ var alwaysCallback;
+ requireCleanWorkspace(function(cancelled) {
+ if (cancelled) {
+ if (options.cancel) {
+ options.cancel();
+ if (alwaysCallback) {
+ alwaysCallback();
+ }
+ }
+ } else {
+ delete options.requireCleanWorkspace;
+ sendRequest(options,body).then(function() {
+ if (thenCallback) {
+ thenCallback();
+ }
+ }).always(function() {
+ if (alwaysCallback) {
+ alwaysCallback();
+ }
+
+ })
+ }
+ })
+ // What follows is a very hacky Promise-like api thats good enough
+ // for our needs.
return {
+ then: function(done) {
+ thenCallback = done;
+ return { always: function(done) { alwaysCallback = done; }}
+ },
always: function(done) { alwaysCallback = done; }
}
}
@@ -1806,6 +1844,13 @@ RED.projects = (function() {
}
+ function showNewProjectScreen() {
+ if (!activeProject) {
+ show('welcome');
+ } else {
+ show('create')
+ }
+ }
return {
init: init,
@@ -1821,10 +1866,15 @@ RED.projects = (function() {
RED.notify(RED._("user.errors.notAuthorized"),"error");
return;
}
- if (!activeProject) {
- show('welcome');
+
+ if (RED.nodes.dirty()) {
+ return requireCleanWorkspace(function(cancelled) {
+ if (!cancelled) {
+ showNewProjectScreen();
+ }
+ })
} else {
- show('create')
+ showNewProjectScreen();
}
},
selectProject: function() {
diff --git a/editor/sass/notifications.scss b/editor/sass/notifications.scss
index 096fa607d..9a66f1683 100644
--- a/editor/sass/notifications.scss
+++ b/editor/sass/notifications.scss
@@ -36,7 +36,7 @@
}
.notification p:first-child {
font-size: 1.1em;
- font-weight: 500;
+ font-weight: 400;
}
.notification a {
text-decoration: none;
diff --git a/red/api/editor/locales/en-US/editor.json b/red/api/editor/locales/en-US/editor.json
index 9390605e2..73a2b3758 100644
--- a/red/api/editor/locales/en-US/editor.json
+++ b/red/api/editor/locales/en-US/editor.json
@@ -88,9 +88,9 @@
"warnings": {
"undeployedChanges": "node has undeployed changes",
"nodeActionDisabled": "node actions disabled within subflow",
- "missing-types": "Flows stopped due to missing node types. Check logs for details.",
+ "missing-types": "
Flows stopped due to missing node types.
",
"restartRequired": "Node-RED must be restarted to enable upgraded modules",
- "credentials_load_failed": "
Flows stopped due to missing or invalid credentialSecret.
",
+ "credentials_load_failed": "
Flows stopped as the credentials could not be decrypted.
The flow credential file is encrypted, but the project's encryption key is missing or invalid.
",
"missing_flow_file": "
Project flow file not found.
The project is not configured with a flow file.
",
"project_empty": "
The project is empty.
Do you want to create a default set of project files?
Otherwise, you will have to manually add files to the project outside of the editor.
"
},
diff --git a/red/api/editor/settings.js b/red/api/editor/settings.js
index 0668f3631..9aeafb1ca 100644
--- a/red/api/editor/settings.js
+++ b/red/api/editor/settings.js
@@ -17,11 +17,13 @@ var theme = require("../editor/theme");
var util = require('util');
var runtime;
var settings;
+var log;
module.exports = {
init: function(_runtime) {
runtime = _runtime;
settings = runtime.settings;
+ log = runtime.log;
},
runtimeSettings: function(req,res) {
var safeSettings = {
diff --git a/red/runtime/nodes/flows/index.js b/red/runtime/nodes/flows/index.js
index 26c76cd30..5fdb2ef35 100644
--- a/red/runtime/nodes/flows/index.js
+++ b/red/runtime/nodes/flows/index.js
@@ -254,7 +254,7 @@ function start(type,diff,muteLog) {
log.info(log._("nodes.flows.missing-type-install-2"));
log.info(" "+settings.userDir);
}
- events.emit("runtime-event",{id:"runtime-state",payload:{type:"warning",text:"notification.warnings.missing-types"},retain:true});
+ events.emit("runtime-event",{id:"runtime-state",payload:{error:"missing-types", type:"warning",text:"notification.warnings.missing-types",types:activeFlowConfig.missingTypes},retain:true});
return when.resolve();
}
if (!muteLog) {
diff --git a/red/runtime/storage/localfilesystem/projects/Project.js b/red/runtime/storage/localfilesystem/projects/Project.js
index 46817d397..14547e129 100644
--- a/red/runtime/storage/localfilesystem/projects/Project.js
+++ b/red/runtime/storage/localfilesystem/projects/Project.js
@@ -32,6 +32,15 @@ var projectsDir;
var authCache = require("./git/authCache");
+// TODO: DRY - red/api/editor/sshkeys !
+function getSSHKeyUsername(userObj) {
+ var username = '__default';
+ if ( userObj && userObj.name ) {
+ username = userObj.name;
+ }
+ return username;
+}
+
function Project(name) {
this.name = name;
this.path = fspath.join(projectsDir,name);
@@ -645,7 +654,7 @@ Project.prototype.updateRemote = function(user,remote,options) {
if (options.auth) {
var url = this.remotes[remote].fetch;
if (options.auth.keyFile) {
- options.auth.key_path = sshKeys.getPrivateKeyPath(username, options.auth.keyFile);
+ options.auth.key_path = sshKeys.getPrivateKeyPath(getSSHKeyUsername(user), options.auth.keyFile);
}
authCache.set(this.name,url,username,options.auth);
}
@@ -662,7 +671,7 @@ Project.prototype.removeRemote = function(user, remote) {
Project.prototype.getFlowFile = function() {
- console.log("Project.getFlowFile = ",this.paths.flowFile);
+ // console.log("Project.getFlowFile = ",this.paths.flowFile);
if (this.paths.flowFile) {
return fspath.join(this.path,this.paths.flowFile);
} else {
@@ -674,7 +683,7 @@ Project.prototype.getFlowFileBackup = function() {
return getBackupFilename(this.getFlowFile());
}
Project.prototype.getCredentialsFile = function() {
- console.log("Project.getCredentialsFile = ",this.paths.credentialsFile);
+ // console.log("Project.getCredentialsFile = ",this.paths.credentialsFile);
if (this.paths.credentialsFile) {
return fspath.join(this.path,this.paths.credentialsFile);
} else {
@@ -872,7 +881,7 @@ function createProject(user, metadata) {
}
else if (originRemote.hasOwnProperty("keyFile") && originRemote.hasOwnProperty("passphrase")) {
authCache.set(project,originRemote.url,username,{ // TODO: hardcoded remote name
- key_path: sshKeys.getPrivateKeyPath(username, originRemote.keyFile),
+ key_path: sshKeys.getPrivateKeyPath(getSSHKeyUsername(user), originRemote.keyFile),
passphrase: originRemote.passphrase
}
);
diff --git a/red/runtime/storage/localfilesystem/projects/git/authServer.js b/red/runtime/storage/localfilesystem/projects/git/authServer.js
index 3e04e2c3c..d38ea9fd0 100644
--- a/red/runtime/storage/localfilesystem/projects/git/authServer.js
+++ b/red/runtime/storage/localfilesystem/projects/git/authServer.js
@@ -45,7 +45,7 @@ var ResponseServer = function(auth) {
parts.push(data.substring(0, m));
data = data.substring(m);
var line = parts.join("");
- console.log("LINE:",line);
+ // console.log("LINE:",line);
parts = [];
if (line==='Username') {
connection.end(auth.username);
@@ -90,7 +90,6 @@ var ResponseSSHServer = function(auth) {
parts.push(data.substring(0, m));
data = data.substring(m);
var line = parts.join("");
- console.log("LINE:",line);
parts = [];
if (line==='The') {
// TODO: document these exchanges!
diff --git a/red/runtime/storage/localfilesystem/projects/index.js b/red/runtime/storage/localfilesystem/projects/index.js
index b4dac444f..86cdfb245 100644
--- a/red/runtime/storage/localfilesystem/projects/index.js
+++ b/red/runtime/storage/localfilesystem/projects/index.js
@@ -23,7 +23,7 @@ var crypto = require('crypto');
var storageSettings = require("../settings");
var util = require("../util");
var gitTools = require("./git");
-var sshTools = require("./ssh");
+var sshTools = require("./sshKeygen");
var Projects = require("./Project");
diff --git a/red/runtime/storage/localfilesystem/projects/ssh.js b/red/runtime/storage/localfilesystem/projects/sshKeygen.js
similarity index 100%
rename from red/runtime/storage/localfilesystem/projects/ssh.js
rename to red/runtime/storage/localfilesystem/projects/sshKeygen.js
diff --git a/test/red/runtime/storage/localfilesystem/projects/ssh_spec.js b/test/red/runtime/storage/localfilesystem/projects/sshKeygen_spec.js
similarity index 99%
rename from test/red/runtime/storage/localfilesystem/projects/ssh_spec.js
rename to test/red/runtime/storage/localfilesystem/projects/sshKeygen_spec.js
index c71d83268..0dab247ad 100644
--- a/test/red/runtime/storage/localfilesystem/projects/ssh_spec.js
+++ b/test/red/runtime/storage/localfilesystem/projects/sshKeygen_spec.js
@@ -19,7 +19,7 @@ var sinon = require("sinon");
var child_process = require('child_process');
var EventEmitter = require("events");
-var ssh = require("../../../../../../red/runtime/storage/localfilesystem/projects/ssh")
+var ssh = require("../../../../../../red/runtime/storage/localfilesystem/projects/sshKeygen")
describe("localfilesystem/projects/ssh", function() {