1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Update sshey UI to use common list style

This commit is contained in:
Nick O'Leary 2017-12-20 23:45:17 +00:00
parent 3b51d18ce7
commit 816442f5f0
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
4 changed files with 250 additions and 151 deletions

View File

@ -1088,14 +1088,15 @@ RED.projects.settings = (function() {
.appendTo(title) .appendTo(title)
.click(function(evt) { .click(function(evt) {
editRepoButton.attr('disabled',true); editRepoButton.attr('disabled',true);
addBranchDialog.slideDown(200, function() { addRemoteDialog.slideDown(200, function() {
addBranchDialog[0].scrollIntoView(); addRemoteDialog[0].scrollIntoView();
}); });
}); });
var emptyItem = { empty: true }; var emptyItem = { empty: true };
var row = $('<div class="user-settings-row"></div>').appendTo(repoContainer);
var addRemoteDialog = $('<div class="projects-dialog-list-dialog"></div>').hide().appendTo(row);
row = $('<div class="user-settings-row projects-dialog-list"></div>').appendTo(repoContainer); row = $('<div class="user-settings-row projects-dialog-list"></div>').appendTo(repoContainer);
var remotesList = $('<ol>').appendTo(row); var remotesList = $('<ol>').appendTo(row);
remotesList.editableList({ remotesList.editableList({
@ -1192,7 +1193,7 @@ RED.projects.settings = (function() {
} }
}; };
var popover; var popover;
var addRemoteDialog = $('<div class="projects-dialog-list-dialog"></div>').hide().appendTo(row);
$('<div class="projects-dialog-list-dialog-header">').text('Add remote').appendTo(addRemoteDialog); $('<div class="projects-dialog-list-dialog-header">').text('Add remote').appendTo(addRemoteDialog);
row = $('<div class="user-settings-row"></div>').appendTo(addRemoteDialog); row = $('<div class="user-settings-row"></div>').appendTo(addRemoteDialog);
@ -1204,7 +1205,7 @@ RED.projects.settings = (function() {
var remoteNameInputChanged = false; var remoteNameInputChanged = false;
$('<label class="projects-edit-form-sublabel"><small>Must contain only A-Z 0-9 _ -</small></label>').appendTo(row).find("small"); $('<label class="projects-edit-form-sublabel"><small>Must contain only A-Z 0-9 _ -</small></label>').appendTo(row).find("small");
row = $('<div class="user-settings-row"></div>').appendTo(addRemoteDialog); row = $('<div class="user-settings-row"></div>').appendTo(addRemoteDialog);
var fetchLabel = $('<label for=""></label>').text('URL').appendTo(row); $('<label for=""></label>').text('URL').appendTo(row);
var remoteURLInput = $('<input type="text">').appendTo(row).on("change keyup paste",validateForm); var remoteURLInput = $('<input type="text">').appendTo(row).on("change keyup paste",validateForm);
var hideEditForm = function() { var hideEditForm = function() {

View File

@ -16,18 +16,17 @@
RED.projects.userSettings = (function() { RED.projects.userSettings = (function() {
var gitconfigContainer;
var gitUsernameInput; var gitUsernameInput;
var gitEmailInput; var gitEmailInput;
function createRemoteRepositorySection(pane) { function createGitUserSection(pane) {
var currentGitSettings = RED.settings.get('git') || {}; var currentGitSettings = RED.settings.get('git') || {};
currentGitSettings.user = currentGitSettings.user || {}; currentGitSettings.user = currentGitSettings.user || {};
var title = $('<h3></h3>').text("Committer Details").appendTo(pane); var title = $('<h3></h3>').text("Committer Details").appendTo(pane);
gitconfigContainer = $('<div class="user-settings-section"></div>').appendTo(pane); var gitconfigContainer = $('<div class="user-settings-section"></div>').appendTo(pane);
$('<div style="color:#aaa;"></div>').appendTo(gitconfigContainer).text("Leave blank to use system default"); $('<div style="color:#aaa;"></div>').appendTo(gitconfigContainer).text("Leave blank to use system default");
var row = $('<div class="user-settings-row"></div>').appendTo(gitconfigContainer); var row = $('<div class="user-settings-row"></div>').appendTo(gitconfigContainer);
@ -39,162 +38,248 @@ RED.projects.userSettings = (function() {
$('<label for=""></label>').text('Email').appendTo(row); $('<label for=""></label>').text('Email').appendTo(row);
gitEmailInput = $('<input type="text">').appendTo(row); gitEmailInput = $('<input type="text">').appendTo(row);
gitEmailInput.val(currentGitSettings.user.email||""); gitEmailInput.val(currentGitSettings.user.email||"");
}
var sshkeyTitle = $('<h4></h4>').text("SSH Keys").appendTo(gitconfigContainer);
var editSshKeyListButton = $('<button class="editor-button editor-button-small" style="float: right;">edit</button>') function createSSHKeySection(pane) {
.appendTo(sshkeyTitle) var container = $('<div class="user-settings-section"></div>').appendTo(pane);
var popover;
var title = $('<h4></h4>').text("SSH Keys").appendTo(container);
var addKeyButton = $('<button class="editor-button editor-button-small" style="float: right; margin-right: 10px;">generate key</button>')
.appendTo(title)
.click(function(evt) { .click(function(evt) {
editSshKeyListButton.hide(); addKeyButton.attr('disabled',true);
formButtons.show(); addKeyDialog.slideDown(200, function() {
sshkeyInputRow.show(); // addKeyDialog[0].scrollIntoView();
$(".projects-dialog-sshkey-list-button-remove").css('display', 'inline-block'); });
}); });
var sshkeyListOptions = { var validateForm = function() {
height: "300px", var validName = /^[a-zA-Z0-9\-_]+$/.test(keyNameInput.val());
deleteAction: function(entry, header) { saveButton.attr('disabled',!validName);
var spinner = utils.addSpinnerOverlay(header).addClass('projects-dialog-spinner-contain'); keyNameInput.toggleClass('input-error',keyNameInputChanged&&!validName);
var notification = RED.notify("Are you sure you want to delete the SSH Keys '"+entry.name+"'? This cannot be undone.", { if (popover) {
type: 'warning', popover.close();
modal: true, popover = null;
fixed: true,
buttons: [
{
text: RED._("common.label.cancel"),
click: function() {
spinner.remove();
notification.close();
}
},
{
text: "Delete SSH Keys",
click: function() {
notification.close();
sendSSHKeyManagementAPI("DELETE_KEY", entry.name, null, function(data) {
spinner.remove();
hideSSHKeyGenerateForm();
utils.refreshSSHKeyList(sshkeysList);
}, function(err) {
spinner.remove();
console.log('Delete error! error:', err);
notification = RED.notify("Failed to delete the SSH Keys '"+entry.name+"'.", {
type: "error",
modal: true,
fixed: false
});
});
}
}
]
});
},
selectAction: function(entry, header) {
var spinner = utils.addSpinnerOverlay(header).addClass('projects-dialog-spinner-contain');
sendSSHKeyManagementAPI("GET_KEY_DETAIL", entry.name, null, function(data) {
spinner.remove();
setDialogContext(entry.name, data.publickey);
dialog.dialog("open");
}, function(err) {
console.log('Get SSH Key detail error! error:', err);
spinner.remove();
notification = RED.notify("Failed to get the SSH Key detail '"+entry.name+"'.", {
type: "error",
modal: true,
fixed: false
});
});
} }
}; };
var sshkeysListRow = $('<div class="user-settings-row projects-dialog-sshkeylist"></div>').appendTo(gitconfigContainer);
var sshkeysList = utils.createSSHKeyList(sshkeyListOptions).appendTo(sshkeysListRow);
var sshkeyInputRow = $('<div class="user-settings-row"></div>').hide().appendTo(gitconfigContainer); var row = $('<div class="user-settings-row"></div>').appendTo(container);
var sshkeyNameLabel = $('<label for=""></label>').text('Key Name').appendTo(sshkeyInputRow); var addKeyDialog = $('<div class="projects-dialog-list-dialog"></div>').hide().appendTo(row);
var sshkeyNameInput = $('<input type="text">').appendTo(sshkeyInputRow); $('<div class="projects-dialog-list-dialog-header">').text('Generate SSH Key').appendTo(addKeyDialog);
var sshkeyPassphraseLabel = $('<label for=""></label>').text('Passphrase').appendTo(sshkeyInputRow);
var sshkeyPassphraseInput = $('<input type="password">').appendTo(sshkeyInputRow);
var sshkeySamePassphraseLabel = $('<label for=""></label>').text('Same Passphrase').appendTo(sshkeyInputRow);
var sshkeySamePassphraseInput = $('<input type="password">').appendTo(sshkeyInputRow);
var formButtonArea = $('<div style="width: 100%; height: 35px;"></div>').appendTo(gitconfigContainer); row = $('<div class="user-settings-row"></div>').appendTo(addKeyDialog);
var formButtons = $('<span class="button-group" style="position: absolute; right: 0px; margin-right: 0px;"></span>') $('<label for=""></label>').text('Name').appendTo(row);
.hide().appendTo(formButtonArea); var keyNameInput = $('<input type="text">').appendTo(row).on("change keyup paste",function() {
keyNameInputChanged = true;
validateForm();
});
var keyNameInputChanged = false;
$('<label class="projects-edit-form-sublabel"><small>Must contain only A-Z 0-9 _ -</small></label>').appendTo(row).find("small");
function hideSSHKeyGenerateForm() { row = $('<div class="user-settings-row"></div>').appendTo(addKeyDialog);
editSshKeyListButton.show(); $('<label for=""></label>').text('Passphrase').appendTo(row);
formButtons.hide(); passphraseInput = $('<input type="password">').appendTo(row).on("change keyup paste",validateForm);
sshkeyInputRow.hide(); $('<label class="projects-edit-form-sublabel"><small>Optional</small></label>').appendTo(row).find("small");
sshkeyNameInput.val("");
sshkeyPassphraseInput.val(""); var hideEditForm = function() {
sshkeySamePassphraseInput.val(""); addKeyButton.attr('disabled',false);
if ( sshkeyNameInput.hasClass('input-error') ) { addKeyDialog.hide();
sshkeyNameInput.removeClass('input-error'); keyNameInput.val("");
passphraseInput.val("");
if (popover) {
popover.close();
popover = null;
} }
if ( sshkeyPassphraseInput.hasClass('input-error') ) {
sshkeyPassphraseInput.removeClass('input-error');
}
if ( sshkeySamePassphraseInput.hasClass('input-error') ) {
sshkeySamePassphraseInput.removeClass('input-error');
}
$(".projects-dialog-sshkey-list-button-remove").hide();
} }
var formButtons = $('<span class="button-row" style="position: relative; float: right; margin: 10px;"></span>').appendTo(addKeyDialog);
$('<button class="editor-button">Cancel</button>') $('<button class="editor-button">Cancel</button>')
.appendTo(formButtons) .appendTo(formButtons)
.click(function(evt) { .click(function(evt) {
evt.preventDefault(); evt.preventDefault();
hideSSHKeyGenerateForm(); hideEditForm();
}); });
var generateButton = $('<button class="editor-button">Generate</button>') var saveButton = $('<button class="editor-button">Generate key</button>')
.appendTo(formButtons) .appendTo(formButtons)
.click(function(evt) { .click(function(evt) {
evt.preventDefault(); evt.preventDefault();
if ( sshkeyNameInput.hasClass('input-error') ) { var spinner = utils.addSpinnerOverlay(addKeyDialog).addClass('projects-dialog-spinner-contain');
sshkeyNameInput.removeClass('input-error'); var payload = {
name: keyNameInput.val(),
comment: gitEmailInput.val(),
password: passphraseInput.val(),
size: 4096
};
var done = function(err) {
spinner.remove();
if (err) {
return;
}
hideEditForm();
} }
if ( sshkeyPassphraseInput.hasClass('input-error') ) { // console.log(JSON.stringify(payload,null,4));
sshkeyPassphraseInput.removeClass('input-error'); RED.deploy.setDeployInflight(true);
} utils.sendRequest({
if ( sshkeySamePassphraseInput.hasClass('input-error') ) { url: "settings/user/keys",
sshkeySamePassphraseInput.removeClass('input-error'); type: "POST",
} responses: {
var valid = true; 0: function(error) {
if ( sshkeyNameInput.val() === "" ) { done(error);
sshkeyNameInput.addClass('input-error');
valid = false;
}
if ( sshkeyPassphraseInput.val() !== sshkeySamePassphraseInput.val() ) {
sshkeySamePassphraseInput.addClass('input-error');
valid = false;
}
if ( valid ) {
sendSSHKeyManagementAPI("GENERATE_KEY",
{
name: sshkeyNameInput.val(),
email: gitEmailInput.val(),
password: sshkeyPassphraseInput.val(),
size: 4096
}, },
gitconfigContainer, 200: function(data) {
function() { refreshSSHKeyList();
hideSSHKeyGenerateForm(); done();
utils.refreshSSHKeyList(sshkeysList);
}, },
function(err) { 400: {
console.log('err message:', err.message); 'unexpected_error': function(error) {
if ( err.message.includes('Some SSH Keyfile exists') ) { console.log(error);
sshkeyNameInput.addClass('input-error'); done(error);
} }
else if ( err.message.includes('Failed to generate ssh key files') ) { },
sshkeyPassphraseInput.addClass('input-error'); }
sshkeySamePassphraseInput.addClass('input-error'); },payload);
}
}
);
}
}); });
row = $('<div class="user-settings-row projects-dialog-list"></div>').appendTo(container);
var emptyItem = { empty: true };
var expandKey = function(container,entry) {
var row = $('<div class="projects-dialog-ssh-public-key">',{style:"position:relative"}).appendTo(container);
var keyBox = $('<pre>',{style:"min-height: 80px"}).appendTo(row);
var spinner = utils.addSpinnerOverlay(keyBox).addClass('projects-dialog-spinner-contain');
var options = {
url: 'settings/user/keys/'+entry.name,
type: "GET",
responses: {
200: function(data) {
keyBox.text(data.publickey);
spinner.remove();
},
400: {
'unexpected_error': function(error) {
console.log(error);
spinner.remove();
}
},
}
}
utils.sendRequest(options);
var formButtons = $('<span class="button-row" style="position: relative; float: right; margin: 10px;"></span>').appendTo(row);
$('<button class="editor-button editor-button-small">Copy to Clipboard</button>')
.appendTo(formButtons)
.click(function(evt) {
evt.preventDefault();
document.getSelection().selectAllChildren(keyBox[0]);
var ret = document.execCommand('copy');
document.getSelection().empty();
});
return row;
}
var keyList = $('<ol>').appendTo(row).editableList({
height: 'auto',
addButton: false,
scrollOnAdd: false,
addItem: function(row,index,entry) {
var container = $('<div class="projects-dialog-list-entry">').appendTo(row);
if (entry.empty) {
container.addClass('red-ui-search-empty');
container.text("No SSH keys");
return;
}
$('<span class="entry-icon"><i class="fa fa-key"></i></span>').appendTo(container);
var content = $('<span>').appendTo(container);
var topRow = $('<div>').appendTo(content);
$('<span class="entry-name">').text(entry.name).appendTo(topRow);
var tools = $('<span class="button-row entry-tools">').appendTo(container);
var expandedRow;
$('<button class="editor-button editor-button-small"><i class="fa fa-eye"></i></button>')
.appendTo(tools)
.click(function(e) {
if (expandedRow) {
expandedRow.slideUp(200,function() {
expandedRow.remove();
expandedRow = null;
})
} else {
expandedRow = expandKey(container,entry);
}
})
$('<button class="editor-button editor-button-small"><i class="fa fa-trash"></i></button>')
.appendTo(tools)
.click(function(e) {
var spinner = utils.addSpinnerOverlay(row).addClass('projects-dialog-spinner-contain');
var notification = RED.notify("Are you sure you want to delete the SSH key '"+entry.name+"'? This cannot be undone.", {
type: 'warning',
modal: true,
fixed: true,
buttons: [
{
text: RED._("common.label.cancel"),
click: function() {
spinner.remove();
notification.close();
}
},
{
text: "Delete key",
click: function() {
notification.close();
var url = "settings/user/keys/"+entry.name;
var options = {
url: url,
type: "DELETE",
responses: {
200: function(data) {
row.fadeOut(200,function() {
keyList.editableList('removeItem',entry);
setTimeout(spinner.remove, 100);
if (keyList.editableList('length') === 0) {
keyList.editableList('addItem',emptyItem);
}
});
},
400: {
'unexpected_error': function(error) {
console.log(error);
spinner.remove();
}
},
}
}
utils.sendRequest(options);
}
}
]
});
});
}
});
var refreshSSHKeyList = function() {
$.getJSON("settings/user/keys",function(result) {
if (result.keys) {
result.keys.sort(function(A,B) {
return A.name.localeCompare(B.name);
});
keyList.editableList('empty');
result.keys.forEach(function(key) {
keyList.editableList('addItem',key);
})
}
})
}
refreshSSHKeyList();
} }
function sendSSHKeyManagementAPI(type, param, overlay, successCallback, failCallback) { function sendSSHKeyManagementAPI(type, param, overlay, successCallback, failCallback) {
var url; var url;
var method; var method;
@ -320,7 +405,9 @@ RED.projects.userSettings = (function() {
function createSettingsPane(activeProject) { function createSettingsPane(activeProject) {
var pane = $('<div id="user-settings-tab-gitconfig" class="project-settings-tab-pane node-help"></div>'); var pane = $('<div id="user-settings-tab-gitconfig" class="project-settings-tab-pane node-help"></div>');
createRemoteRepositorySection(pane); createGitUserSection(pane);
createSSHKeySection(pane);
createPublicKeyDialog(); createPublicKeyDialog();
return pane; return pane;
} }

View File

@ -756,9 +756,17 @@
} }
div.projects-dialog-ssh-public-key { div.projects-dialog-ssh-public-key {
position: relative;
padding: 15px 20px 0;
pre { pre {
position: relative;
word-break: break-all; word-break: break-all;
} }
&:after {
content: "";
display: table;
clear: both;
}
} }
.projects-dialog-list { .projects-dialog-list {
@ -808,10 +816,8 @@ div.projects-dialog-ssh-public-key {
} }
} }
.projects-dialog-list-dialog { .projects-dialog-list-dialog {
position: absolute; margin-top: 10px;
top: 5px; margin-bottom: 20px;
right: 10px;
left: 10px;
background: white; background: white;
border-radius: 4px; border-radius: 4px;
border: 1px solid $secondary-border-color; border: 1px solid $secondary-border-color;
@ -820,6 +826,11 @@ div.projects-dialog-ssh-public-key {
display: block !important; display: block !important;
width: auto !important; width: auto !important;
} }
&:after {
content: "";
display: table;
clear: both;
}
.projects-dialog-list-dialog-header { .projects-dialog-list-dialog-header {
font-weight: bold; font-weight: bold;

View File

@ -92,12 +92,12 @@ function generateSSHKey(username, options) {
throw new Error('Some SSH Keyfile exists'); throw new Error('Some SSH Keyfile exists');
} }
else { else {
var email = options.email || ""; var comment = options.comment || "";
var password = options.password || ""; var password = options.password || "";
var size = options.size || 2048; var size = options.size || 2048;
var sshKeyFileBasename = username + '_' + name; var sshKeyFileBasename = username + '_' + name;
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename); var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
return generateSSHKeyPair(privateKeyFilePath, email, password, size) return generateSSHKeyPair(privateKeyFilePath, comment, password, size)
.then(function() { .then(function() {
return name; return name;
}); });