mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge sshkeys
This commit is contained in:
commit
8c87478636
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
RED.projects.userSettings = (function() {
|
RED.projects.userSettings = (function() {
|
||||||
|
|
||||||
|
var gitconfigContainer;
|
||||||
var gitUsernameInput;
|
var gitUsernameInput;
|
||||||
var gitEmailInput;
|
var gitEmailInput;
|
||||||
|
|
||||||
@ -24,11 +25,9 @@ RED.projects.userSettings = (function() {
|
|||||||
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);
|
||||||
|
|
||||||
var gitconfigContainer = $('<div class="user-settings-section"></div>').appendTo(pane);
|
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);
|
||||||
@ -40,77 +39,289 @@ 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 generateSshKeyButton = $('<button class="editor-button editor-button-small" style="float: right;">generate new ssh key</button>')
|
|
||||||
// .appendTo(sshkeyTitle)
|
|
||||||
// .click(function(evt) {
|
|
||||||
// console.log('click generateSshKeyButton');
|
|
||||||
// });
|
|
||||||
|
|
||||||
// row = $('<div class="user-settings-row projects-dialog-remote-list"></div>').appendTo(gitconfigContainer);
|
var sshkeyTitle = $('<h4></h4>').text("SSH Keys").appendTo(gitconfigContainer);
|
||||||
// var sshkeysList = $('<ol>').appendTo(row);
|
var editSshKeyListButton = $('<button class="editor-button editor-button-small" style="float: right;">edit</button>')
|
||||||
// sshkeysList.editableList({
|
.appendTo(sshkeyTitle)
|
||||||
// addButton: false,
|
.click(function(evt) {
|
||||||
// height: 'auto',
|
editSshKeyListButton.hide();
|
||||||
// addItem: function(outer,index,entry) {
|
formButtons.show();
|
||||||
|
sshkeyInputRow.show();
|
||||||
|
$(".projects-dialog-sshkey-list-button-remove").css('display', 'inline-block');
|
||||||
|
});
|
||||||
|
|
||||||
|
var sshkeyListOptions = {
|
||||||
|
height: "300px",
|
||||||
|
deleteAction: function(entry, header) {
|
||||||
|
var spinner = utils.addSpinnerOverlay(header).addClass('projects-dialog-spinner-contain');
|
||||||
|
var notification = RED.notify("Are you sure you want to delete the SSH Keys '"+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 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 header = $('<div class="projects-dialog-remote-list-entry-header"></div>').appendTo(outer);
|
var sshkeyInputRow = $('<div class="user-settings-row"></div>').hide().appendTo(gitconfigContainer);
|
||||||
// entry.header = $('<span>').text(entry.path||"Add new remote").appendTo(header);
|
var sshkeyNameLabel = $('<label for=""></label>').text('Key Name').appendTo(sshkeyInputRow);
|
||||||
// var body = $('<div>').appendTo(outer);
|
var sshkeyNameInput = $('<input type="text">').appendTo(sshkeyInputRow);
|
||||||
// entry.body = body;
|
var sshkeyPassphraseLabel = $('<label for=""></label>').text('Passphrase').appendTo(sshkeyInputRow);
|
||||||
// if (entry.path) {
|
var sshkeyPassphraseInput = $('<input type="password">').appendTo(sshkeyInputRow);
|
||||||
// entry.removeButton = $('<button class="editor-button editor-button-small projects-dialog-remote-list-entry-delete">remove</button>')
|
var sshkeySamePassphraseLabel = $('<label for=""></label>').text('Same Passphrase').appendTo(sshkeyInputRow);
|
||||||
// // .hide()
|
var sshkeySamePassphraseInput = $('<input type="password">').appendTo(sshkeyInputRow);
|
||||||
// .appendTo(header)
|
|
||||||
// .click(function(e) {
|
|
||||||
// entry.removed = true;
|
|
||||||
// body.fadeOut(100);
|
|
||||||
// entry.header.css("text-decoration","line-through")
|
|
||||||
// entry.header.css("font-style","italic")
|
|
||||||
// if (entry.copyToClipboard) {
|
|
||||||
// entry.copyToClipboard.hide();
|
|
||||||
// }
|
|
||||||
// $(this).hide();
|
|
||||||
// });
|
|
||||||
// if (entry.data) {
|
|
||||||
// entry.copyToClipboard = $('<button class="editor-button editor-button-small projects-dialog-remote-list-entry-copy">copy</button>')
|
|
||||||
// // .hide()
|
|
||||||
// .appendTo(header)
|
|
||||||
// .click(function(e) {
|
|
||||||
// var textarea = document.createElement("textarea");
|
|
||||||
// textarea.style.position = 'fixed';
|
|
||||||
// textarea.style.top = 0;
|
|
||||||
// textarea.style.left = 0;
|
|
||||||
// textarea.style.width = '2em';
|
|
||||||
// textarea.style.height = '2em';
|
|
||||||
// textarea.style.padding = 0;
|
|
||||||
// textarea.style.border = 'none';
|
|
||||||
// textarea.style.outline = 'none';
|
|
||||||
// textarea.style.boxShadow = 'none';
|
|
||||||
// textarea.style.background = 'transparent';
|
|
||||||
// textarea.value = entry.data;
|
|
||||||
// document.body.appendChild(textarea);
|
|
||||||
// textarea.select();
|
|
||||||
// try {
|
|
||||||
// var ret = document.execCommand('copy');
|
|
||||||
// var msg = ret ? 'successful' : 'unsuccessful';
|
|
||||||
// console.log('Copy text command was ' + msg);
|
|
||||||
// } catch (err) {
|
|
||||||
// console.log('Oops unable to copy');
|
|
||||||
// }
|
|
||||||
// document.body.removeChild(textarea);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// var remoteListAddButton = row.find(".red-ui-editableList-addButton").hide();
|
var formButtonArea = $('<div style="width: 100%; height: 35px;"></div>').appendTo(gitconfigContainer);
|
||||||
|
var formButtons = $('<span class="button-group" style="position: absolute; right: 0px; margin-right: 0px;"></span>')
|
||||||
|
.hide().appendTo(formButtonArea);
|
||||||
|
|
||||||
|
function hideSSHKeyGenerateForm() {
|
||||||
|
editSshKeyListButton.show();
|
||||||
|
formButtons.hide();
|
||||||
|
sshkeyInputRow.hide();
|
||||||
|
sshkeyNameInput.val("");
|
||||||
|
sshkeyPassphraseInput.val("");
|
||||||
|
sshkeySamePassphraseInput.val("");
|
||||||
|
if ( sshkeyNameInput.hasClass('input-error') ) {
|
||||||
|
sshkeyNameInput.removeClass('input-error');
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
$('<button class="editor-button">Cancel</button>')
|
||||||
|
.appendTo(formButtons)
|
||||||
|
.click(function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
hideSSHKeyGenerateForm();
|
||||||
|
});
|
||||||
|
var generateButton = $('<button class="editor-button">Generate</button>')
|
||||||
|
.appendTo(formButtons)
|
||||||
|
.click(function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
if ( sshkeyNameInput.hasClass('input-error') ) {
|
||||||
|
sshkeyNameInput.removeClass('input-error');
|
||||||
|
}
|
||||||
|
if ( sshkeyPassphraseInput.hasClass('input-error') ) {
|
||||||
|
sshkeyPassphraseInput.removeClass('input-error');
|
||||||
|
}
|
||||||
|
if ( sshkeySamePassphraseInput.hasClass('input-error') ) {
|
||||||
|
sshkeySamePassphraseInput.removeClass('input-error');
|
||||||
|
}
|
||||||
|
var valid = true;
|
||||||
|
if ( sshkeyNameInput.val() === "" ) {
|
||||||
|
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,
|
||||||
|
function() {
|
||||||
|
hideSSHKeyGenerateForm();
|
||||||
|
utils.refreshSSHKeyList(sshkeysList);
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
console.log('err message:', err.message);
|
||||||
|
if ( err.message.includes('Some SSH Keyfile exists') ) {
|
||||||
|
sshkeyNameInput.addClass('input-error');
|
||||||
|
}
|
||||||
|
else if ( err.message.includes('Failed to generate ssh key files') ) {
|
||||||
|
sshkeyPassphraseInput.addClass('input-error');
|
||||||
|
sshkeySamePassphraseInput.addClass('input-error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendSSHKeyManagementAPI(type, param, overlay, successCallback, failCallback) {
|
||||||
|
var url;
|
||||||
|
var method;
|
||||||
|
var payload;
|
||||||
|
switch(type) {
|
||||||
|
case 'GET_KEY_LIST':
|
||||||
|
method = 'GET';
|
||||||
|
url = "settings/user/keys";
|
||||||
|
break;
|
||||||
|
case 'GET_KEY_DETAIL':
|
||||||
|
method = 'GET';
|
||||||
|
url = "settings/user/keys/" + param;
|
||||||
|
break;
|
||||||
|
case 'GENERATE_KEY':
|
||||||
|
method = 'POST';
|
||||||
|
url = "settings/user/keys";
|
||||||
|
payload= param;
|
||||||
|
break;
|
||||||
|
case 'DELETE_KEY':
|
||||||
|
method = 'DELETE';
|
||||||
|
url = "settings/user/keys/" + param;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.error('Unexpected type....');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// var spinner = utils.addSpinnerOverlay(gitconfigContainer);
|
||||||
|
var spinner = overlay ? utils.addSpinnerOverlay(overlay) : null;
|
||||||
|
|
||||||
|
var done = function(err) {
|
||||||
|
if ( spinner ) {
|
||||||
|
spinner.remove();
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('method:', method);
|
||||||
|
console.log('url:', url);
|
||||||
|
|
||||||
|
utils.sendRequest({
|
||||||
|
url: url,
|
||||||
|
type: method,
|
||||||
|
responses: {
|
||||||
|
0: function(error) {
|
||||||
|
if ( failCallback ) {
|
||||||
|
failCallback(error);
|
||||||
|
}
|
||||||
|
done(error);
|
||||||
|
},
|
||||||
|
200: function(data) {
|
||||||
|
if ( successCallback ) {
|
||||||
|
successCallback(data);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
'unexpected_error': function(error) {
|
||||||
|
console.log(error);
|
||||||
|
if ( failCallback ) {
|
||||||
|
failCallback(error);
|
||||||
|
}
|
||||||
|
done(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dialog;
|
||||||
|
var dialogBody;
|
||||||
|
function createPublicKeyDialog() {
|
||||||
|
dialog = $('<div id="projects-dialog" class="hide node-red-dialog projects-edit-form"><form class="form-horizontal"></form></div>')
|
||||||
|
.appendTo("body")
|
||||||
|
.dialog({
|
||||||
|
modal: true,
|
||||||
|
autoOpen: false,
|
||||||
|
width: 600,
|
||||||
|
resize: false,
|
||||||
|
open: function(e) {
|
||||||
|
$(this).parent().find(".ui-dialog-titlebar-close").hide();
|
||||||
|
},
|
||||||
|
close: function(e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialogBody = dialog.find("form");
|
||||||
|
dialog.dialog('option', 'title', 'SSH public key');
|
||||||
|
dialog.dialog('option', 'buttons', [
|
||||||
|
{
|
||||||
|
text: RED._("common.label.close"),
|
||||||
|
click: function() {
|
||||||
|
$( this ).dialog( "close" );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Copy to Clipboard",
|
||||||
|
click: function() {
|
||||||
|
var target = document.getElementById('public-key-data');
|
||||||
|
document.getSelection().selectAllChildren(target);
|
||||||
|
var ret = document.execCommand('copy');
|
||||||
|
var msg = ret ? 'successful' : 'unsuccessful';
|
||||||
|
console.log('Copy text command was ' + msg);
|
||||||
|
$( this ).dialog("close");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
dialog.dialog({position: { 'my': 'center', 'at': 'center', 'of': window }});
|
||||||
|
var container = $('<div class="projects-dialog-screen-start"></div>');
|
||||||
|
$('<div class="projects-dialog-ssh-public-key-name"></div>').appendTo(container);
|
||||||
|
$('<div class="projects-dialog-ssh-public-key"><pre id="public-key-data"></pre></div>').appendTo(container);
|
||||||
|
dialogBody.append(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDialogContext(name, data) {
|
||||||
|
var title = dialog.find("div.projects-dialog-ssh-public-key-name");
|
||||||
|
title.text(name);
|
||||||
|
var context = dialog.find("div.projects-dialog-ssh-public-key>pre");
|
||||||
|
context.text(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
createRemoteRepositorySection(pane);
|
||||||
|
createPublicKeyDialog();
|
||||||
return pane;
|
return pane;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,6 +465,7 @@ RED.projects = (function() {
|
|||||||
var projectRepoUserInput;
|
var projectRepoUserInput;
|
||||||
var projectRepoPasswordInput;
|
var projectRepoPasswordInput;
|
||||||
var projectNameSublabel;
|
var projectNameSublabel;
|
||||||
|
var projectRepoSSHKeySelect;
|
||||||
var projectRepoPassphrase;
|
var projectRepoPassphrase;
|
||||||
var projectRepoRemoteName
|
var projectRepoRemoteName
|
||||||
var projectRepoBranch;
|
var projectRepoBranch;
|
||||||
@ -537,12 +538,18 @@ RED.projects = (function() {
|
|||||||
if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(repo)) {
|
if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(repo)) {
|
||||||
$(".projects-dialog-screen-create-row-creds").hide();
|
$(".projects-dialog-screen-create-row-creds").hide();
|
||||||
$(".projects-dialog-screen-create-row-passphrase").show();
|
$(".projects-dialog-screen-create-row-passphrase").show();
|
||||||
|
$(".projects-dialog-screen-create-row-sshkey").show();
|
||||||
|
if ( !getSelectedSSHKey(projectRepoSSHKeySelect) ) {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
} else if (/^https?:\/\//.test(repo)) {
|
} else if (/^https?:\/\//.test(repo)) {
|
||||||
$(".projects-dialog-screen-create-row-creds").show();
|
$(".projects-dialog-screen-create-row-creds").show();
|
||||||
$(".projects-dialog-screen-create-row-passphrase").hide();
|
$(".projects-dialog-screen-create-row-passphrase").hide();
|
||||||
|
$(".projects-dialog-screen-create-row-sshkey").hide();
|
||||||
} else {
|
} else {
|
||||||
$(".projects-dialog-screen-create-row-creds").show();
|
$(".projects-dialog-screen-create-row-creds").show();
|
||||||
$(".projects-dialog-screen-create-row-passphrase").hide();
|
$(".projects-dialog-screen-create-row-passphrase").hide();
|
||||||
|
$(".projects-dialog-screen-create-row-sshkey").hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -569,7 +576,7 @@ RED.projects = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#projects-dialog-create").prop('disabled',!valid).toggleClass('disabled ui-button-disabled ui-state-disabled',!valid);
|
$("#projects-dialog-create").prop('disabled',!valid).toggleClass('disabled ui-button-disabled ui-state-disabled',!valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,6 +756,16 @@ RED.projects = (function() {
|
|||||||
$('<label for="projects-dialog-screen-create-project-repo-pass">Password</label>').appendTo(subrow);
|
$('<label for="projects-dialog-screen-create-project-repo-pass">Password</label>').appendTo(subrow);
|
||||||
projectRepoPasswordInput = $('<input id="projects-dialog-screen-create-project-repo-pass" type="password"></input>').appendTo(subrow);
|
projectRepoPasswordInput = $('<input id="projects-dialog-screen-create-project-repo-pass" type="password"></input>').appendTo(subrow);
|
||||||
|
|
||||||
|
row = $('<div class="form-row projects-dialog-screen-create-row projects-dialog-screen-create-row-sshkey"></div>').hide().appendTo(container);
|
||||||
|
$('<label for="projects-dialog-screen-create-project-repo-passphrase">SSH Private key file</label>').appendTo(row);
|
||||||
|
projectRepoSSHKeySelect = createSSHKeyList({
|
||||||
|
height: "120px",
|
||||||
|
selectAction: function(entry, header) {
|
||||||
|
$('.projects-dialog-sshkey-list-entry').removeClass('selected');
|
||||||
|
header.addClass('selected');
|
||||||
|
}
|
||||||
|
}).appendTo(row);
|
||||||
|
|
||||||
row = $('<div class="form-row projects-dialog-screen-create-row projects-dialog-screen-create-row-passphrase"></div>').hide().appendTo(container);
|
row = $('<div class="form-row projects-dialog-screen-create-row projects-dialog-screen-create-row-passphrase"></div>').hide().appendTo(container);
|
||||||
$('<label for="projects-dialog-screen-create-project-repo-passphrase">SSH key passphrase</label>').appendTo(row);
|
$('<label for="projects-dialog-screen-create-project-repo-passphrase">SSH key passphrase</label>').appendTo(row);
|
||||||
projectRepoPassphrase = $('<input id="projects-dialog-screen-create-project-repo-passphrase" type="password" style="width: calc(100% - 250px);"></input>').appendTo(row);
|
projectRepoPassphrase = $('<input id="projects-dialog-screen-create-project-repo-passphrase" type="password" style="width: calc(100% - 250px);"></input>').appendTo(row);
|
||||||
@ -818,14 +835,36 @@ RED.projects = (function() {
|
|||||||
projectData.copy = copyProject.name;
|
projectData.copy = copyProject.name;
|
||||||
} else if (projectType === 'clone') {
|
} else if (projectType === 'clone') {
|
||||||
// projectData.credentialSecret = projectSecretInput.val();
|
// projectData.credentialSecret = projectSecretInput.val();
|
||||||
projectData.git = {
|
var repoUrl = projectRepoInput.val();
|
||||||
remotes: {
|
var metaData = {};
|
||||||
'origin': {
|
if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(repoUrl)) {
|
||||||
url: projectRepoInput.val(),
|
var selected = getSelectedSSHKey(projectRepoSSHKeySelect);
|
||||||
username: projectRepoUserInput.val(),
|
if ( selected && selected.name ) {
|
||||||
password: projectRepoPasswordInput.val()
|
projectData.git = {
|
||||||
}
|
remotes: {
|
||||||
|
'origin': {
|
||||||
|
url: repoUrl,
|
||||||
|
key_file: selected.name,
|
||||||
|
passphrase: projectRepoPassphrase.val()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
console.log("Error! Can't get selected SSH key path.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
projectData.git = {
|
||||||
|
remotes: {
|
||||||
|
'origin': {
|
||||||
|
url: repoUrl,
|
||||||
|
username: projectRepoUserInput.val(),
|
||||||
|
password: projectRepoPasswordInput.val()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -855,6 +894,8 @@ RED.projects = (function() {
|
|||||||
projectRepoUserInput.addClass("input-error");
|
projectRepoUserInput.addClass("input-error");
|
||||||
projectRepoPasswordInput.addClass("input-error");
|
projectRepoPasswordInput.addClass("input-error");
|
||||||
// getRepoAuthDetails(req);
|
// getRepoAuthDetails(req);
|
||||||
|
projectRepoSSHKeySelect.addClass("input-error");
|
||||||
|
projectRepoPassphrase.addClass("input-error");
|
||||||
console.log("git auth error",error);
|
console.log("git auth error",error);
|
||||||
},
|
},
|
||||||
'unexpected_error': function(error) {
|
'unexpected_error': function(error) {
|
||||||
@ -1115,6 +1156,87 @@ RED.projects = (function() {
|
|||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createSSHKeyList(options) {
|
||||||
|
options = options || {};
|
||||||
|
var minHeight = "33px";
|
||||||
|
var maxHeight = options.height || "120px";
|
||||||
|
var container = $('<div></div>',{style:"max-height: "+maxHeight+";"});
|
||||||
|
|
||||||
|
var sshkeyList = $('<ol>',{class:"projects-dialog-sshkey-list", style:"max-height:"+maxHeight+";min-height:"+minHeight+";"}).appendTo(container).editableList({
|
||||||
|
addButton: false,
|
||||||
|
scrollOnAdd: false,
|
||||||
|
addItem: function(row,index,entry) {
|
||||||
|
var header = $('<div></div>',{class:"projects-dialog-sshkey-list-entry"}).appendTo(row);
|
||||||
|
$('<span class="projects-dialog-sshkey-list-entry-icon"><i class="fa fa-key"></i></span>').appendTo(header);
|
||||||
|
$('<span class="projects-dialog-sshkey-list-entry-name" style=""></span>').text(entry.name).appendTo(header);
|
||||||
|
var deleteButton = $('<span/>',{class:"projects-dialog-sshkey-list-entry-icon projects-dialog-sshkey-list-button-remove editor-button editor-button-small"})
|
||||||
|
.hide()
|
||||||
|
.appendTo(header)
|
||||||
|
.click(function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
console.log('deleteButton --- click');
|
||||||
|
if ( options.deleteAction ) {
|
||||||
|
options.deleteAction(entry, header);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$('<i/>',{class:"fa fa-trash-o"}).appendTo(deleteButton);
|
||||||
|
header.addClass("selectable");
|
||||||
|
row.click(function(evt) {
|
||||||
|
if ( !deleteButton.is(":visible") ) {
|
||||||
|
if ( options.selectAction ) {
|
||||||
|
options.selectAction(entry, header);
|
||||||
|
}
|
||||||
|
$.data(container[0], 'selected', entry);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$.getJSON("settings/user/keys", function(data) {
|
||||||
|
data.keys.forEach(function(key) {
|
||||||
|
if ( sshkeyList ) {
|
||||||
|
sshkeyList.editableList('addItem',key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('[create] Error! selectedSSHKey is not set up.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if ( sshkeyList ) {
|
||||||
|
sshkeyList.addClass("projects-dialog-sshkey-list-small");
|
||||||
|
$.data(container[0], 'selected', null);
|
||||||
|
$.data(container[0], 'sshkeys', sshkeyList);
|
||||||
|
}
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
function getSelectedSSHKey(container) {
|
||||||
|
var selected = $.data(container[0], 'selected');
|
||||||
|
if ( container && selected ) {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function refreshSSHKeyList(container) {
|
||||||
|
var sshkeyList = $.data(container[0], 'sshkeys');
|
||||||
|
if ( container && sshkeyList ) {
|
||||||
|
sshkeyList.empty();
|
||||||
|
$.getJSON("settings/user/keys", function(data) {
|
||||||
|
var keyList = $.data(container[0], 'sshkeys');
|
||||||
|
data.keys.forEach(function(key) {
|
||||||
|
if ( keyList ) {
|
||||||
|
keyList.editableList('addItem',key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('[refresh] Error! selectedSSHKey is not set up.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function sendRequest(options,body) {
|
function sendRequest(options,body) {
|
||||||
// dialogBody.hide();
|
// dialogBody.hide();
|
||||||
console.log(options.url,body);
|
console.log(options.url,body);
|
||||||
@ -1431,7 +1553,9 @@ RED.projects = (function() {
|
|||||||
var projectsAPI = {
|
var projectsAPI = {
|
||||||
sendRequest:sendRequest,
|
sendRequest:sendRequest,
|
||||||
createBranchList:createBranchList,
|
createBranchList:createBranchList,
|
||||||
addSpinnerOverlay:addSpinnerOverlay
|
addSpinnerOverlay:addSpinnerOverlay,
|
||||||
|
createSSHKeyList:createSSHKeyList,
|
||||||
|
refreshSSHKeyList:refreshSSHKeyList
|
||||||
};
|
};
|
||||||
RED.projects.settings.init(projectsAPI);
|
RED.projects.settings.init(projectsAPI);
|
||||||
RED.projects.userSettings.init(projectsAPI);
|
RED.projects.userSettings.init(projectsAPI);
|
||||||
|
@ -675,6 +675,92 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.projects-dialog-sshkey-list {
|
||||||
|
li {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
&.projects-dialog-sshkey-list-small {
|
||||||
|
.projects-dialog-sshkey-list-entry {
|
||||||
|
padding: 6px 0;
|
||||||
|
i {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.projects-dialog-sshkey-list-entry-name {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
.projects-dialog-sshkey-list-entry-current {
|
||||||
|
margin-right: 10px;
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.red-ui-editableList-container {
|
||||||
|
.projects-dialog-sshkey-list {
|
||||||
|
li:last-child {
|
||||||
|
border-bottom: 0px none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.projects-dialog-sshkey-list-entry {
|
||||||
|
padding: 12px 0;
|
||||||
|
border-left: 3px solid #fff;
|
||||||
|
border-right: 3px solid #fff;
|
||||||
|
&.sshkey-list-entry-current {
|
||||||
|
&:not(.selectable) {
|
||||||
|
background: #f9f9f9;
|
||||||
|
}
|
||||||
|
i {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.selectable {
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background: #f3f3f3;
|
||||||
|
border-left-color: #aaa;
|
||||||
|
border-right-color: #aaa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i {
|
||||||
|
color: #ccc;
|
||||||
|
font-size: 2em;
|
||||||
|
|
||||||
|
}
|
||||||
|
&.selected {
|
||||||
|
background: #efefef;
|
||||||
|
border-left-color:#999;
|
||||||
|
border-right-color:#999;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align:middle;
|
||||||
|
}
|
||||||
|
.projects-dialog-sshkey-list-entry-icon {
|
||||||
|
margin: 0 10px 0 5px;
|
||||||
|
}
|
||||||
|
.projects-dialog-sshkey-list-entry-name {
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
.projects-dialog-sshkey-list-entry-current {
|
||||||
|
float: right;
|
||||||
|
margin-right: 20px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #999;
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
.projects-dialog-sshkey-list-button-remove {
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.projects-dialog-ssh-public-key {
|
||||||
|
pre {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.projects-dialog-list {
|
.projects-dialog-list {
|
||||||
position: relative;
|
position: relative;
|
||||||
.red-ui-editableList-container {
|
.red-ui-editableList-container {
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
"raw-body":"2.2.0",
|
"raw-body":"2.2.0",
|
||||||
"semver": "5.3.0",
|
"semver": "5.3.0",
|
||||||
"sentiment":"2.1.0",
|
"sentiment":"2.1.0",
|
||||||
|
"ssh-keygen":"0.4.1",
|
||||||
"uglify-js":"3.0.20",
|
"uglify-js":"3.0.20",
|
||||||
"when": "3.7.8",
|
"when": "3.7.8",
|
||||||
"ws": "1.1.1",
|
"ws": "1.1.1",
|
||||||
|
@ -97,6 +97,10 @@ module.exports = {
|
|||||||
// User Settings
|
// User Settings
|
||||||
editorApp.post("/settings/user",needsPermission("settings.write"),info.updateUserSettings,apiUtil.errorHandler);
|
editorApp.post("/settings/user",needsPermission("settings.write"),info.updateUserSettings,apiUtil.errorHandler);
|
||||||
|
|
||||||
|
// SSH keys
|
||||||
|
var sshkeys = require("./sshkeys");
|
||||||
|
sshkeys.init(runtime);
|
||||||
|
editorApp.use("/settings/user/keys",sshkeys.app());
|
||||||
|
|
||||||
return editorApp;
|
return editorApp;
|
||||||
}
|
}
|
||||||
|
125
red/api/editor/sshkeys.js
Normal file
125
red/api/editor/sshkeys.js
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/**
|
||||||
|
* 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 express = require("express");
|
||||||
|
var os = require("os");
|
||||||
|
var runtime;
|
||||||
|
var settings;
|
||||||
|
var needsPermission = require("../auth").needsPermission;
|
||||||
|
|
||||||
|
function getUsername(userObj) {
|
||||||
|
var username = '.default';
|
||||||
|
if ( userObj && userObj.name ) {
|
||||||
|
username = userObj.name;
|
||||||
|
}
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
init: function(_runtime) {
|
||||||
|
runtime = _runtime;
|
||||||
|
settings = runtime.settings;
|
||||||
|
},
|
||||||
|
app: function() {
|
||||||
|
var app = express();
|
||||||
|
|
||||||
|
// SSH keys
|
||||||
|
|
||||||
|
// List all SSH keys
|
||||||
|
app.get("/", needsPermission("settings.read"), function(req,res) {
|
||||||
|
var username = getUsername(req.user);
|
||||||
|
runtime.storage.sshkeys.listSSHKeys(username)
|
||||||
|
.then(function(list) {
|
||||||
|
res.json({
|
||||||
|
keys: list
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
// console.log(err.stack);
|
||||||
|
if (err.code) {
|
||||||
|
res.status(400).json({error:err.code, message: err.message});
|
||||||
|
} else {
|
||||||
|
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get SSH key detail
|
||||||
|
app.get("/:id", needsPermission("settings.read"), function(req,res) {
|
||||||
|
var username = getUsername(req.user);
|
||||||
|
// console.log('username:', username);
|
||||||
|
runtime.storage.sshkeys.getSSHKey(username, req.params.id)
|
||||||
|
.then(function(data) {
|
||||||
|
res.json({
|
||||||
|
publickey: data
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
console.log(err.stack);
|
||||||
|
if (err.code) {
|
||||||
|
res.status(400).json({error:err.code, message: err.message});
|
||||||
|
} else {
|
||||||
|
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Generate a SSH key
|
||||||
|
app.post("/", needsPermission("settings.write"), function(req,res) {
|
||||||
|
var username = getUsername(req.user);
|
||||||
|
// console.log('req.body:', req.body);
|
||||||
|
if ( req.body && req.body.name ) {
|
||||||
|
runtime.storage.sshkeys.generateSSHKey(username, req.body)
|
||||||
|
.then(function(name) {
|
||||||
|
// console.log('generate key --- success name:', name);
|
||||||
|
res.json({
|
||||||
|
name: name
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
console.log(err.stack);
|
||||||
|
if (err.code) {
|
||||||
|
res.status(400).json({error:err.code, message: err.message});
|
||||||
|
} else {
|
||||||
|
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res.status(400).json({error:"unexpected_error", message:"You need to have body or body.name"});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete a SSH key
|
||||||
|
app.delete("/:id", needsPermission("settings.write"), function(req,res) {
|
||||||
|
var username = getUsername(req.user);
|
||||||
|
runtime.storage.sshkeys.deleteSSHKey(username, req.params.id)
|
||||||
|
.then(function(ret) {
|
||||||
|
res.status(204).end();
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
console.log(err.stack);
|
||||||
|
if (err.code) {
|
||||||
|
res.status(400).json({error:err.code, message: err.message});
|
||||||
|
} else {
|
||||||
|
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
}
|
@ -63,6 +63,9 @@ var storageModuleInterface = {
|
|||||||
storageModuleInterface.projects = storageModule.projects;
|
storageModuleInterface.projects = storageModule.projects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (storageModule.sshkeys) {
|
||||||
|
storageModuleInterface.sshkeys = storageModule.sshkeys;
|
||||||
|
}
|
||||||
return storageModule.init(runtime.settings,runtime);
|
return storageModule.init(runtime.settings,runtime);
|
||||||
},
|
},
|
||||||
getFlows: function() {
|
getFlows: function() {
|
||||||
|
@ -24,6 +24,7 @@ var library = require("./library");
|
|||||||
var sessions = require("./sessions");
|
var sessions = require("./sessions");
|
||||||
var runtimeSettings = require("./settings");
|
var runtimeSettings = require("./settings");
|
||||||
var projects = require("./projects");
|
var projects = require("./projects");
|
||||||
|
var sshkeys = require("./sshkeys");
|
||||||
|
|
||||||
var initialFlowLoadComplete = false;
|
var initialFlowLoadComplete = false;
|
||||||
var settings;
|
var settings;
|
||||||
@ -60,6 +61,7 @@ var localfilesystem = {
|
|||||||
runtimeSettings.init(settings);
|
runtimeSettings.init(settings);
|
||||||
promises.push(library.init(settings));
|
promises.push(library.init(settings));
|
||||||
promises.push(projects.init(settings, runtime));
|
promises.push(projects.init(settings, runtime));
|
||||||
|
promises.push(sshkeys.init(settings, runtime));
|
||||||
|
|
||||||
var packageFile = fspath.join(settings.userDir,"package.json");
|
var packageFile = fspath.join(settings.userDir,"package.json");
|
||||||
var packagePromise = when.resolve();
|
var packagePromise = when.resolve();
|
||||||
@ -94,7 +96,8 @@ var localfilesystem = {
|
|||||||
saveSessions: sessions.saveSessions,
|
saveSessions: sessions.saveSessions,
|
||||||
getLibraryEntry: library.getLibraryEntry,
|
getLibraryEntry: library.getLibraryEntry,
|
||||||
saveLibraryEntry: library.saveLibraryEntry,
|
saveLibraryEntry: library.saveLibraryEntry,
|
||||||
projects: projects
|
projects: projects,
|
||||||
|
sshkeys: sshkeys
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = localfilesystem;
|
module.exports = localfilesystem;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
var fs = require('fs-extra');
|
var fs = require('fs-extra');
|
||||||
var when = require('when');
|
var when = require('when');
|
||||||
var fspath = require("path");
|
var fspath = require("path");
|
||||||
|
var os = require('os');
|
||||||
|
|
||||||
var gitTools = require("./git");
|
var gitTools = require("./git");
|
||||||
var util = require("../util");
|
var util = require("../util");
|
||||||
@ -753,6 +754,7 @@ function createProject(user, metadata) {
|
|||||||
if (metadata.git && metadata.git.remotes && metadata.git.remotes.origin) {
|
if (metadata.git && metadata.git.remotes && metadata.git.remotes.origin) {
|
||||||
var originRemote = metadata.git.remotes.origin;
|
var originRemote = metadata.git.remotes.origin;
|
||||||
var auth;
|
var auth;
|
||||||
|
console.log('originRemote:', originRemote);
|
||||||
if (originRemote.hasOwnProperty("username") && originRemote.hasOwnProperty("password")) {
|
if (originRemote.hasOwnProperty("username") && originRemote.hasOwnProperty("password")) {
|
||||||
authCache.set(project,originRemote.url,username,{ // TODO: hardcoded remote name
|
authCache.set(project,originRemote.url,username,{ // TODO: hardcoded remote name
|
||||||
username: originRemote.username,
|
username: originRemote.username,
|
||||||
@ -761,6 +763,15 @@ function createProject(user, metadata) {
|
|||||||
);
|
);
|
||||||
auth = authCache.get(project,originRemote.url,username);
|
auth = authCache.get(project,originRemote.url,username);
|
||||||
}
|
}
|
||||||
|
else if (originRemote.hasOwnProperty("key_file") && originRemote.hasOwnProperty("passphrase")) {
|
||||||
|
var key_file_name = (username === '_') ? '.default' + '_' + originRemote.key_file : username + '_' + originRemote.key_file;
|
||||||
|
authCache.set(project,originRemote.url,username,{ // TODO: hardcoded remote name
|
||||||
|
key_path: fspath.join(projectsDir, ".sshkeys", key_file_name),
|
||||||
|
passphrase: originRemote.passphrase
|
||||||
|
}
|
||||||
|
);
|
||||||
|
auth = authCache.get(project,originRemote.url,username);
|
||||||
|
}
|
||||||
return gitTools.clone(originRemote,auth,projectPath).then(function(result) {
|
return gitTools.clone(originRemote,auth,projectPath).then(function(result) {
|
||||||
// Check this is a valid project
|
// Check this is a valid project
|
||||||
// If it is empty
|
// If it is empty
|
||||||
|
@ -45,7 +45,7 @@ var ResponseServer = function(auth) {
|
|||||||
parts.push(data.substring(0, m));
|
parts.push(data.substring(0, m));
|
||||||
data = data.substring(m);
|
data = data.substring(m);
|
||||||
var line = parts.join("");
|
var line = parts.join("");
|
||||||
console.log("LINE",line);
|
console.log("LINE:",line);
|
||||||
parts = [];
|
parts = [];
|
||||||
if (line==='Username') {
|
if (line==='Username') {
|
||||||
connection.end(auth.username);
|
connection.end(auth.username);
|
||||||
@ -79,8 +79,54 @@ var ResponseServer = function(auth) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ResponseSSHServer = function(auth) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
server = net.createServer(function(connection) {
|
||||||
|
connection.setEncoding('utf8');
|
||||||
|
var parts = [];
|
||||||
|
connection.on('data', function(data) {
|
||||||
|
var m = data.indexOf("\n");
|
||||||
|
if (m !== -1) {
|
||||||
|
parts.push(data.substring(0, m));
|
||||||
|
data = data.substring(m);
|
||||||
|
var line = parts.join("");
|
||||||
|
console.log("LINE:",line);
|
||||||
|
parts = [];
|
||||||
|
if (line==='The') {
|
||||||
|
connection.end('yes');
|
||||||
|
// server.close();
|
||||||
|
} else if (line === 'Enter') {
|
||||||
|
connection.end(auth.passphrase);
|
||||||
|
// server.close();
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.length > 0) {
|
||||||
|
parts.push(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
var listenPath = getListenPath();
|
||||||
|
|
||||||
|
server.listen(listenPath, function(ready) {
|
||||||
|
resolve({path:listenPath,close:function() { server.close(); }});
|
||||||
|
});
|
||||||
|
server.on('close', function() {
|
||||||
|
// console.log("Closing response server");
|
||||||
|
fs.removeSync(listenPath);
|
||||||
|
});
|
||||||
|
server.on('error',function(err) {
|
||||||
|
console.log("ResponseServer unexpectedError:",err.toString());
|
||||||
|
server.close();
|
||||||
|
reject(err);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
ResponseServer: ResponseServer
|
ResponseServer: ResponseServer,
|
||||||
|
ResponseSSHServer: ResponseSSHServer
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ var when = require('when');
|
|||||||
var exec = require('child_process').exec;
|
var exec = require('child_process').exec;
|
||||||
var spawn = require('child_process').spawn;
|
var spawn = require('child_process').spawn;
|
||||||
var authResponseServer = require('./authServer').ResponseServer;
|
var authResponseServer = require('./authServer').ResponseServer;
|
||||||
|
var sshResponseServer = require('./authServer').ResponseSSHServer;
|
||||||
var clone = require('clone');
|
var clone = require('clone');
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
|
||||||
@ -50,6 +51,8 @@ function runGitCommand(args,cwd,env) {
|
|||||||
err.code = "git_auth_failed";
|
err.code = "git_auth_failed";
|
||||||
} else if(/HTTP Basic: Access denied/.test(stderr)) {
|
} else if(/HTTP Basic: Access denied/.test(stderr)) {
|
||||||
err.code = "git_auth_failed";
|
err.code = "git_auth_failed";
|
||||||
|
} else if(/Permission denied \(publickey\)/.test(stderr)) {
|
||||||
|
err.code = "git_auth_failed";
|
||||||
} else if(/Connection refused/.test(stderr)) {
|
} else if(/Connection refused/.test(stderr)) {
|
||||||
err.code = "git_connection_failed";
|
err.code = "git_connection_failed";
|
||||||
} else if (/commit your changes or stash/.test(stderr)) {
|
} else if (/commit your changes or stash/.test(stderr)) {
|
||||||
@ -80,6 +83,22 @@ function runGitCommandWithAuth(args,cwd,auth) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function runGitCommandWithSSHCommand(args,cwd,auth) {
|
||||||
|
return sshResponseServer(auth).then(function(rs) {
|
||||||
|
var commandEnv = clone(process.env);
|
||||||
|
commandEnv.SSH_ASKPASS = path.join(__dirname,"node-red-ask-pass.sh");
|
||||||
|
commandEnv.DISPLAY = "dummy:0";
|
||||||
|
commandEnv.NODE_RED_GIT_NODE_PATH = process.execPath;
|
||||||
|
commandEnv.NODE_RED_GIT_SOCK_PATH = rs.path;
|
||||||
|
commandEnv.NODE_RED_GIT_ASKPASS_PATH = path.join(__dirname,"authWriter.js");
|
||||||
|
commandEnv.GIT_SSH_COMMAND = "ssh -i " + auth.key_path + " -F /dev/null";
|
||||||
|
// console.log('commandEnv:', commandEnv);
|
||||||
|
return runGitCommand(args,cwd,commandEnv).finally(function() {
|
||||||
|
rs.close();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function cleanFilename(name) {
|
function cleanFilename(name) {
|
||||||
if (name[0] !== '"') {
|
if (name[0] !== '"') {
|
||||||
return name;
|
return name;
|
||||||
@ -362,7 +381,12 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
var promise;
|
var promise;
|
||||||
if (auth) {
|
if (auth) {
|
||||||
promise = runGitCommandWithAuth(args,cwd,auth);
|
if ( auth.key_path ) {
|
||||||
|
promise = runGitCommandWithSSHCommand(args,cwd,auth);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
promise = runGitCommandWithAuth(args,cwd,auth);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
promise = runGitCommand(args,cwd)
|
promise = runGitCommand(args,cwd)
|
||||||
}
|
}
|
||||||
@ -393,7 +417,12 @@ module.exports = {
|
|||||||
args.push("--porcelain");
|
args.push("--porcelain");
|
||||||
var promise;
|
var promise;
|
||||||
if (auth) {
|
if (auth) {
|
||||||
promise = runGitCommandWithAuth(args,cwd,auth);
|
if ( auth.key_path ) {
|
||||||
|
promise = runGitCommandWithSSHCommand(args,cwd,auth);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
promise = runGitCommandWithAuth(args,cwd,auth);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
promise = runGitCommand(args,cwd)
|
promise = runGitCommand(args,cwd)
|
||||||
}
|
}
|
||||||
@ -418,7 +447,12 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
args.push(".");
|
args.push(".");
|
||||||
if (auth) {
|
if (auth) {
|
||||||
return runGitCommandWithAuth(args,cwd,auth);
|
if ( auth.key_path ) {
|
||||||
|
return runGitCommandWithSSHCommand(args,cwd,auth);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return runGitCommandWithAuth(args,cwd,auth);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return runGitCommand(args,cwd);
|
return runGitCommand(args,cwd);
|
||||||
}
|
}
|
||||||
@ -477,7 +511,12 @@ module.exports = {
|
|||||||
fetch: function(cwd,remote,auth) {
|
fetch: function(cwd,remote,auth) {
|
||||||
var args = ["fetch",remote];
|
var args = ["fetch",remote];
|
||||||
if (auth) {
|
if (auth) {
|
||||||
return runGitCommandWithAuth(args,cwd,auth);
|
if ( auth.key_path ) {
|
||||||
|
return runGitCommandWithSSHCommand(args,cwd,auth);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return runGitCommandWithAuth(args,cwd,auth);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return runGitCommand(args,cwd);
|
return runGitCommand(args,cwd);
|
||||||
}
|
}
|
||||||
|
190
red/runtime/storage/localfilesystem/sshkeys.js
Normal file
190
red/runtime/storage/localfilesystem/sshkeys.js
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/**
|
||||||
|
* 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 fs = require('fs-extra');
|
||||||
|
var when = require('when');
|
||||||
|
var fspath = require("path");
|
||||||
|
var keygen = require('ssh-keygen');
|
||||||
|
|
||||||
|
var settings;
|
||||||
|
var runtime;
|
||||||
|
var log;
|
||||||
|
var sshkeyDir;
|
||||||
|
|
||||||
|
function init(_settings, _runtime) {
|
||||||
|
settings = _settings;
|
||||||
|
runtime = _runtime;
|
||||||
|
log = runtime.log;
|
||||||
|
sshkeyDir = fspath.join(settings.userDir, "projects", ".sshkeys");
|
||||||
|
// console.log('sshkeys.init()');
|
||||||
|
return createSSHKeyDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSSHKeyDirectory() {
|
||||||
|
return fs.ensureDir(sshkeyDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
function listSSHKeys(username) {
|
||||||
|
var startStr = username + '_';
|
||||||
|
// console.log('sshkeyDir:', sshkeyDir);
|
||||||
|
return fs.readdir(sshkeyDir).then(function(fns) {
|
||||||
|
var ret = fns.sort()
|
||||||
|
.filter(function(fn) {
|
||||||
|
var fullPath = fspath.join(sshkeyDir,fn);
|
||||||
|
if (fn.length > 2 || fn[0] != ".") {
|
||||||
|
var stats = fs.lstatSync(fullPath);
|
||||||
|
if (stats.isFile()) {
|
||||||
|
return fn.startsWith(startStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.map(function(filename) {
|
||||||
|
return filename.substr(startStr.length);
|
||||||
|
})
|
||||||
|
.reduce(function(prev, current) {
|
||||||
|
var parsePath = fspath.parse(current);
|
||||||
|
if ( parsePath ) {
|
||||||
|
if ( parsePath.ext !== '.pub' ) {
|
||||||
|
// Private Keys
|
||||||
|
prev.keyFiles.push(parsePath.base);
|
||||||
|
}
|
||||||
|
else if ( parsePath.ext === '.pub' && (prev.keyFiles.some(function(elem){ return elem === parsePath.name; }))) {
|
||||||
|
prev.privateKeyFiles.push(parsePath.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}, { keyFiles: [], privateKeyFiles: [] });
|
||||||
|
return ret.privateKeyFiles.map(function(filename) {
|
||||||
|
return {
|
||||||
|
name: filename
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSSHKey(username, name) {
|
||||||
|
return checkSSHKeyFileAndGetPublicKeyFileName(username, name)
|
||||||
|
.then(function(publicSSHKeyPath) {
|
||||||
|
return fs.readFile(publicSSHKeyPath, 'utf-8');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateSSHKey(username, options) {
|
||||||
|
options = options || {};
|
||||||
|
var name = options.name || "";
|
||||||
|
return checkExistSSHKeyFiles(username, name)
|
||||||
|
.then(function(result) {
|
||||||
|
if ( result ) {
|
||||||
|
throw new Error('Some SSH Keyfile exists');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var email = options.email || "";
|
||||||
|
var password = options.password || "";
|
||||||
|
var size = options.size || 2048;
|
||||||
|
var sshKeyFileBasename = username + '_' + name;
|
||||||
|
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||||
|
return generateSSHKeyPair(privateKeyFilePath, email, password, size)
|
||||||
|
.then(function() {
|
||||||
|
return name;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function(keyfile_name) {
|
||||||
|
return checkSSHKeyFileAndGetPublicKeyFileName(username, name)
|
||||||
|
.then(function() {
|
||||||
|
return keyfile_name;
|
||||||
|
})
|
||||||
|
.catch(function() {
|
||||||
|
throw new Error('Failed to generate ssh key files');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteSSHKey(username, name) {
|
||||||
|
return checkSSHKeyFileAndGetPublicKeyFileName(username, name)
|
||||||
|
.then(function() {
|
||||||
|
return deleteSSHKeyFiles(username, name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkExistSSHKeyFiles(username, name) {
|
||||||
|
var sshKeyFileBasename = username + '_' + name;
|
||||||
|
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||||
|
var publicKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename + '.pub');
|
||||||
|
return Promise.race([
|
||||||
|
fs.access(privateKeyFilePath, (fs.constants || fs).R_OK),
|
||||||
|
fs.access(publicKeyFilePath , (fs.constants || fs).R_OK)
|
||||||
|
])
|
||||||
|
.then(function() {
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.catch(function() {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSSHKeyFileAndGetPublicKeyFileName(username, name) {
|
||||||
|
var sshKeyFileBasename = username + '_' + name;
|
||||||
|
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||||
|
var publicKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename + '.pub');
|
||||||
|
return Promise.all([
|
||||||
|
fs.access(privateKeyFilePath, (fs.constants || fs).R_OK),
|
||||||
|
fs.access(publicKeyFilePath , (fs.constants || fs).R_OK)
|
||||||
|
])
|
||||||
|
.then(function() {
|
||||||
|
return publicKeyFilePath;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteSSHKeyFiles(username, name) {
|
||||||
|
var sshKeyFileBasename = username + '_' + name;
|
||||||
|
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||||
|
var publicKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename + '.pub');
|
||||||
|
return Promise.all([
|
||||||
|
fs.remove(privateKeyFilePath),
|
||||||
|
fs.remove(publicKeyFilePath)
|
||||||
|
])
|
||||||
|
.then(function(retArray) {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateSSHKeyPair(privateKeyPath, comment, password, size) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
keygen({
|
||||||
|
location: privateKeyPath,
|
||||||
|
comment: comment,
|
||||||
|
password: password,
|
||||||
|
size: size
|
||||||
|
}, function(err, out) {
|
||||||
|
if ( err ) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
init: init,
|
||||||
|
listSSHKeys: listSSHKeys,
|
||||||
|
getSSHKey: getSSHKey,
|
||||||
|
generateSSHKey: generateSSHKey,
|
||||||
|
deleteSSHKey: deleteSSHKey
|
||||||
|
};
|
355
test/red/api/editor/sshkeys_spec.js
Normal file
355
test/red/api/editor/sshkeys_spec.js
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
/**
|
||||||
|
* 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 should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
|
var request = require("supertest");
|
||||||
|
var express = require("express");
|
||||||
|
var editorApi = require("../../../../red/api/editor");
|
||||||
|
var comms = require("../../../../red/api/editor/comms");
|
||||||
|
var info = require("../../../../red/api/editor/settings");
|
||||||
|
var auth = require("../../../../red/api/auth");
|
||||||
|
var sshkeys = require("../../../../red/api/editor/sshkeys");
|
||||||
|
var when = require("when");
|
||||||
|
var bodyParser = require("body-parser");
|
||||||
|
var fs = require("fs-extra");
|
||||||
|
var fspath = require("path");
|
||||||
|
|
||||||
|
|
||||||
|
describe("api/editor/sshkeys", function() {
|
||||||
|
var app;
|
||||||
|
var mockList = [
|
||||||
|
'library','theme','locales','credentials','comms'
|
||||||
|
]
|
||||||
|
var isStarted = true;
|
||||||
|
var errors = [];
|
||||||
|
var session_data = {};
|
||||||
|
|
||||||
|
var mockRuntime = {
|
||||||
|
settings:{
|
||||||
|
httpNodeRoot: true,
|
||||||
|
httpAdminRoot: true,
|
||||||
|
disableEditor: false,
|
||||||
|
exportNodeSettings:function(){},
|
||||||
|
storage: {
|
||||||
|
getSessions: function(){
|
||||||
|
return when.resolve(session_data);
|
||||||
|
},
|
||||||
|
setSessions: function(_session) {
|
||||||
|
session_data = _session;
|
||||||
|
return when.resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
log:{audit:function(){},error:function(msg){errors.push(msg)}}
|
||||||
|
},
|
||||||
|
storage: {
|
||||||
|
sshkeys: {
|
||||||
|
init: function(){},
|
||||||
|
listSSHKeys: function(){},
|
||||||
|
getSSHKey: function(){},
|
||||||
|
generateSSHKey: function(){},
|
||||||
|
deleteSSHKey: function(){},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
events:{on:function(){},removeListener:function(){}},
|
||||||
|
isStarted: function() { return isStarted; },
|
||||||
|
nodes: {paletteEditorEnabled: function() { return false }}
|
||||||
|
};
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
auth.init(mockRuntime);
|
||||||
|
app = express();
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
app.use(editorApi.init({},mockRuntime));
|
||||||
|
});
|
||||||
|
after(function() {
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
sinon.stub(mockRuntime.storage.sshkeys, "listSSHKeys");
|
||||||
|
sinon.stub(mockRuntime.storage.sshkeys, "getSSHKey");
|
||||||
|
sinon.stub(mockRuntime.storage.sshkeys, "generateSSHKey");
|
||||||
|
sinon.stub(mockRuntime.storage.sshkeys, "deleteSSHKey");
|
||||||
|
})
|
||||||
|
afterEach(function() {
|
||||||
|
mockRuntime.storage.sshkeys.listSSHKeys.restore();
|
||||||
|
mockRuntime.storage.sshkeys.getSSHKey.restore();
|
||||||
|
mockRuntime.storage.sshkeys.generateSSHKey.restore();
|
||||||
|
mockRuntime.storage.sshkeys.deleteSSHKey.restore();
|
||||||
|
})
|
||||||
|
|
||||||
|
it('GET /settings/user/keys --- return empty list', function(done) {
|
||||||
|
mockRuntime.storage.sshkeys.listSSHKeys.returns(Promise.resolve([]));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('keys');
|
||||||
|
res.body.keys.should.be.empty();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys --- return normal list', function(done) {
|
||||||
|
var fileList = [
|
||||||
|
'test_key01',
|
||||||
|
'test_key02'
|
||||||
|
];
|
||||||
|
var retList = fileList.map(function(elem) {
|
||||||
|
return {
|
||||||
|
name: elem
|
||||||
|
};
|
||||||
|
});
|
||||||
|
mockRuntime.storage.sshkeys.listSSHKeys.returns(Promise.resolve(retList));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('keys');
|
||||||
|
for (var item of retList) {
|
||||||
|
res.body.keys.should.containEql(item);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys --- return Error', function(done) {
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
errInstance.code = "test_code";
|
||||||
|
mockRuntime.storage.sshkeys.listSSHKeys.returns(Promise.reject(errInstance));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys")
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal(errInstance.code);
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys --- return Unexpected Error', function(done) {
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
mockRuntime.storage.sshkeys.listSSHKeys.returns(Promise.reject(errInstance));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys")
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("unexpected_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.toString());
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys/<key_file_name> --- return content', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
|
||||||
|
mockRuntime.storage.sshkeys.getSSHKey.returns(Promise.resolve(fileContent));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
mockRuntime.storage.sshkeys.getSSHKey.called.should.be.true();
|
||||||
|
res.body.should.be.deepEqual({ publickey: fileContent });
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys/<key_file_name> --- return Error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
errInstance.code = "test_code";
|
||||||
|
mockRuntime.storage.sshkeys.getSSHKey.returns(Promise.reject(errInstance));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal(errInstance.code);
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys/<key_file_name> --- return Unexpected Error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
mockRuntime.storage.sshkeys.getSSHKey.returns(Promise.reject(errInstance));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("unexpected_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.toString());
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('POST /settings/user/keys --- success', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
mockRuntime.storage.sshkeys.generateSSHKey.returns(Promise.resolve(key_file_name));
|
||||||
|
request(app)
|
||||||
|
.post("/settings/user/keys")
|
||||||
|
.send({ name: key_file_name })
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('POST /settings/user/keys --- return parameter error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
mockRuntime.storage.sshkeys.generateSSHKey.returns(Promise.resolve(key_file_name));
|
||||||
|
request(app)
|
||||||
|
.post("/settings/user/keys")
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("unexpected_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal("You need to have body or body.name");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('POST /settings/user/keys --- return Error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
errInstance.code = "test_code";
|
||||||
|
mockRuntime.storage.sshkeys.generateSSHKey.returns(Promise.reject(errInstance));
|
||||||
|
request(app)
|
||||||
|
.post("/settings/user/keys")
|
||||||
|
.send({ name: key_file_name })
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("test_code");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('POST /settings/user/keys --- return Unexpected error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
mockRuntime.storage.sshkeys.generateSSHKey.returns(Promise.reject(errInstance));
|
||||||
|
request(app)
|
||||||
|
.post("/settings/user/keys")
|
||||||
|
.send({ name: key_file_name })
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("unexpected_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.toString());
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('DELETE /settings/user/keys/<key_file_name> --- success', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
mockRuntime.storage.sshkeys.deleteSSHKey.returns(Promise.resolve(true));
|
||||||
|
request(app)
|
||||||
|
.delete("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(204)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.be.deepEqual({});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('DELETE /settings/user/keys/<key_file_name> --- return Error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
errInstance.code = "test_code";
|
||||||
|
mockRuntime.storage.sshkeys.deleteSSHKey.returns(Promise.reject(errInstance));
|
||||||
|
request(app)
|
||||||
|
.delete("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("test_code");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('DELETE /settings/user/keys/<key_file_name> --- return Unexpected Error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
mockRuntime.storage.sshkeys.deleteSSHKey.returns(Promise.reject(errInstance));
|
||||||
|
request(app)
|
||||||
|
.delete("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("unexpected_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.toString());
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
424
test/red/runtime/storage/localfilesystem/sshkeys_spec.js
Normal file
424
test/red/runtime/storage/localfilesystem/sshkeys_spec.js
Normal file
@ -0,0 +1,424 @@
|
|||||||
|
/**
|
||||||
|
* 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 should = require("should");
|
||||||
|
var fs = require('fs-extra');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
var localfilesystem = require("../../../../../red/runtime/storage/localfilesystem");
|
||||||
|
var sshkeys = require("../../../../../red/runtime/storage/localfilesystem/sshkeys");
|
||||||
|
|
||||||
|
describe("storage/localfilesystem/sshkeys", function() {
|
||||||
|
var userDir = path.join(__dirname,".testSSHKeyUserHome");
|
||||||
|
var mockSettings = {
|
||||||
|
userDir: userDir
|
||||||
|
};
|
||||||
|
var mockRuntime = {
|
||||||
|
log:{
|
||||||
|
_:function() { return "placeholder message"},
|
||||||
|
info: function() { },
|
||||||
|
trace: function() { }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
beforeEach(function(done) {
|
||||||
|
fs.remove(userDir,function(err) {
|
||||||
|
fs.mkdir(userDir,done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
afterEach(function(done) {
|
||||||
|
fs.remove(userDir,done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create sshkey directory when sshkey initializes', function(done) {
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
var ret = fs.existsSync(sshkeyDirPath);
|
||||||
|
fs.existsSync(sshkeyDirPath).should.be.true();
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get sshkey empty list if there is no sshkey file', function(done) {
|
||||||
|
var username = 'test';
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.listSSHKeys(username).then(function(retObj) {
|
||||||
|
console.log('retObj:', retObj);
|
||||||
|
retObj.should.be.instanceOf(Array).and.have.lengthOf(0);
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get sshkey list', function(done) {
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var filenameList = ['test-key01', 'test-key02'];
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
for(var filename of filenameList) {
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
|
||||||
|
}
|
||||||
|
sshkeys.listSSHKeys(username).then(function(retObj) {
|
||||||
|
retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
|
||||||
|
for(var filename of filenameList) {
|
||||||
|
retObj.should.containEql({ name: filename });
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not get sshkey file if there is only private key', function(done) {
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var filenameList = ['test-key01', 'test-key02'];
|
||||||
|
var onlyPrivateKeyFilenameList = ['test-key03', 'test-key04'];
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
for(var filename of filenameList) {
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
|
||||||
|
}
|
||||||
|
for(var filename of onlyPrivateKeyFilenameList) {
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
|
||||||
|
}
|
||||||
|
sshkeys.listSSHKeys(username).then(function(retObj) {
|
||||||
|
retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
|
||||||
|
for(var filename of filenameList) {
|
||||||
|
retObj.should.containEql({ name: filename });
|
||||||
|
}
|
||||||
|
for(var filename of onlyPrivateKeyFilenameList) {
|
||||||
|
retObj.should.not.containEql({ name: filename });
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not get sshkey file if there is only public key', function(done) {
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var filenameList = ['test-key01', 'test-key02'];
|
||||||
|
var directoryList = ['test-key03', '.test-key04'];
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
for(var filename of filenameList) {
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
|
||||||
|
}
|
||||||
|
for(var filename of directoryList) {
|
||||||
|
fs.ensureDirSync(path.join(sshkeyDirPath,filename));
|
||||||
|
}
|
||||||
|
sshkeys.listSSHKeys(username).then(function(retObj) {
|
||||||
|
retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
|
||||||
|
for(var filename of filenameList) {
|
||||||
|
retObj.should.containEql({ name: filename });
|
||||||
|
}
|
||||||
|
for(var directoryname of directoryList) {
|
||||||
|
retObj.should.not.containEql({ name: directoryname });
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get sshkey list that does not have directory', function(done) {
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var otherUsername = 'other';
|
||||||
|
var filenameList = ['test-key01', 'test-key02'];
|
||||||
|
var otherUserFilenameList = ['test-key03', 'test-key04'];
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
for(var filename of filenameList) {
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
|
||||||
|
}
|
||||||
|
for(var filename of otherUserFilenameList) {
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename),"","utf8");
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename+".pub"),"","utf8");
|
||||||
|
}
|
||||||
|
sshkeys.listSSHKeys(username).then(function(retObj) {
|
||||||
|
retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
|
||||||
|
for(var filename of filenameList) {
|
||||||
|
retObj.should.containEql({ name: filename });
|
||||||
|
}
|
||||||
|
for(var filename of otherUserFilenameList) {
|
||||||
|
retObj.should.not.containEql({ name: filename });
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get sshkey list that have keys of specified user', function(done) {
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var otherUsername = 'other';
|
||||||
|
var filenameList = ['test-key01', 'test-key02'];
|
||||||
|
var otherUserFilenameList = ['test-key03', 'test-key04'];
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
for(var filename of filenameList) {
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
|
||||||
|
}
|
||||||
|
for(var filename of otherUserFilenameList) {
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename),"","utf8");
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename+".pub"),"","utf8");
|
||||||
|
}
|
||||||
|
sshkeys.listSSHKeys(username).then(function(retObj) {
|
||||||
|
retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
|
||||||
|
for(var filename of filenameList) {
|
||||||
|
retObj.should.containEql({ name: filename });
|
||||||
|
}
|
||||||
|
for(var filename of otherUserFilenameList) {
|
||||||
|
retObj.should.not.containEql({ name: filename });
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate sshkey file with empty data', function(done) {
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var options = {
|
||||||
|
email: 'test@test.com',
|
||||||
|
name: 'test-key01'
|
||||||
|
};
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.generateSSHKey(username, options).then(function(retObj) {
|
||||||
|
retObj.should.be.equal(options.name);
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate sshkey file with password data', function(done) {
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var options = {
|
||||||
|
email: 'test@test.com',
|
||||||
|
name: 'test-key01',
|
||||||
|
password: 'testtest'
|
||||||
|
};
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.generateSSHKey(username, options).then(function(retObj) {
|
||||||
|
retObj.should.be.equal(options.name);
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate sshkey file with size data', function(done) {
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var options = {
|
||||||
|
email: 'test@test.com',
|
||||||
|
name: 'test-key01',
|
||||||
|
size: 4096
|
||||||
|
};
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.generateSSHKey(username, options).then(function(retObj) {
|
||||||
|
retObj.should.be.equal(options.name);
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate sshkey file with password & size data', function(done) {
|
||||||
|
this.timeout(5000);
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var options = {
|
||||||
|
email: 'test@test.com',
|
||||||
|
name: 'test-key01',
|
||||||
|
password: 'testtest',
|
||||||
|
size: 4096
|
||||||
|
};
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.generateSSHKey(username, options).then(function(retObj) {
|
||||||
|
retObj.should.be.equal(options.name);
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not generate sshkey file with illegal size data', function(done) {
|
||||||
|
this.timeout(5000);
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var options = {
|
||||||
|
email: 'test@test.com',
|
||||||
|
name: 'test-key01',
|
||||||
|
size: 3333
|
||||||
|
};
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.generateSSHKey(username, options).then(function(retObj) {
|
||||||
|
retObj.should.be.equal(options.name);
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get sshkey file content', function(done) {
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var filename = 'test-key01';
|
||||||
|
var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),fileContent,"utf8");
|
||||||
|
sshkeys.getSSHKey(username, filename).then(function(retObj) {
|
||||||
|
retObj.should.be.equal(fileContent);
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete sshkey files', function(done) {
|
||||||
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
|
var username = 'test';
|
||||||
|
var filename = 'test-key01';
|
||||||
|
var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
|
||||||
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
|
||||||
|
fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),fileContent,"utf8");
|
||||||
|
sshkeys.deleteSSHKey(username, filename).then(function(retObj) {
|
||||||
|
retObj.should.be.true();
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+filename)).should.be.false();
|
||||||
|
fs.existsSync(path.join(sshkeyDirPath,username+'_'+filename+'.pub')).should.be.false();
|
||||||
|
done();
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}).catch(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user