mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add Git access feature via SSH and Enhance SSH Key management
This commit is contained in:
parent
3a311c9584
commit
fe10b8650f
@ -16,6 +16,7 @@
|
||||
|
||||
RED.projects.userSettings = (function() {
|
||||
|
||||
var gitconfigContainer;
|
||||
var gitUsernameInput;
|
||||
var gitEmailInput;
|
||||
|
||||
@ -24,11 +25,9 @@ RED.projects.userSettings = (function() {
|
||||
var currentGitSettings = RED.settings.get('git') || {};
|
||||
currentGitSettings.user = currentGitSettings.user || {};
|
||||
|
||||
|
||||
|
||||
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");
|
||||
|
||||
var row = $('<div class="user-settings-row"></div>').appendTo(gitconfigContainer);
|
||||
@ -40,77 +39,245 @@ RED.projects.userSettings = (function() {
|
||||
$('<label for=""></label>').text('Email').appendTo(row);
|
||||
gitEmailInput = $('<input type="text">').appendTo(row);
|
||||
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 sshkeysList = $('<ol>').appendTo(row);
|
||||
// sshkeysList.editableList({
|
||||
// addButton: false,
|
||||
// height: 'auto',
|
||||
// addItem: function(outer,index,entry) {
|
||||
var sshkeyTitle = $('<h4></h4>').text("SSH Keys").appendTo(gitconfigContainer);
|
||||
var editSshKeyListButton = $('<button class="editor-button editor-button-small" style="float: right;">edit</button>')
|
||||
.appendTo(sshkeyTitle)
|
||||
.click(function(evt) {
|
||||
editSshKeyListButton.hide();
|
||||
formButtons.show();
|
||||
sshkeyInputRow.show();
|
||||
$(".projects-dialog-sshkey-list-button-remove").css('display', 'inline-block');
|
||||
});
|
||||
|
||||
// var header = $('<div class="projects-dialog-remote-list-entry-header"></div>').appendTo(outer);
|
||||
// entry.header = $('<span>').text(entry.path||"Add new remote").appendTo(header);
|
||||
// var body = $('<div>').appendTo(outer);
|
||||
// entry.body = body;
|
||||
// if (entry.path) {
|
||||
// entry.removeButton = $('<button class="editor-button editor-button-small projects-dialog-remote-list-entry-delete">remove</button>')
|
||||
// // .hide()
|
||||
// .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 sshkeyListOptions = {
|
||||
height: "300px",
|
||||
deleteAction: function(entry, header) {
|
||||
sendSSHKeyManagementAPI("DELETE_KEY", entry.name, function(data) {
|
||||
hideSSHKeyGenerateForm();
|
||||
utils.refreshSSHKeyList(sshkeysList);
|
||||
});
|
||||
},
|
||||
selectAction: function(entry, header) {
|
||||
sendSSHKeyManagementAPI("GET_KEY_DETAIL", entry.name, function(data) {
|
||||
setDialogContext(entry.name, data.publickey);
|
||||
dialog.dialog("open");
|
||||
});
|
||||
}
|
||||
};
|
||||
var sshkeysListRow = $('<div class="user-settings-row projects-dialog-sshkeylist"></div>').appendTo(gitconfigContainer);
|
||||
var sshkeysList = utils.createSSHKeyList(sshkeyListOptions).appendTo(sshkeysListRow);
|
||||
|
||||
// var remoteListAddButton = row.find(".red-ui-editableList-addButton").hide();
|
||||
var sshkeyInputRow = $('<div class="user-settings-row"></div>').hide().appendTo(gitconfigContainer);
|
||||
var sshkeyNameLabel = $('<label for=""></label>').text('Key Name').appendTo(sshkeyInputRow);
|
||||
var sshkeyNameInput = $('<input type="text">').appendTo(sshkeyInputRow);
|
||||
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);
|
||||
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
|
||||
},
|
||||
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, 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 done = function(err) {
|
||||
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) {
|
||||
var pane = $('<div id="user-settings-tab-gitconfig" class="project-settings-tab-pane node-help"></div>');
|
||||
createRemoteRepositorySection(pane);
|
||||
createPublicKeyDialog();
|
||||
return pane;
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,7 @@ RED.projects = (function() {
|
||||
var projectRepoUserInput;
|
||||
var projectRepoPasswordInput;
|
||||
var projectNameSublabel;
|
||||
var projectRepoSSHKeySelect;
|
||||
var projectRepoPassphrase;
|
||||
var projectRepoRemoteName
|
||||
var projectRepoBranch;
|
||||
@ -126,12 +127,18 @@ RED.projects = (function() {
|
||||
if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(repo)) {
|
||||
$(".projects-dialog-screen-create-row-creds").hide();
|
||||
$(".projects-dialog-screen-create-row-passphrase").show();
|
||||
$(".projects-dialog-screen-create-row-sshkey").show();
|
||||
if ( !getSelectedSSHKey(projectRepoSSHKeySelect) ) {
|
||||
valid = false;
|
||||
}
|
||||
} else if (/^https?:\/\//.test(repo)) {
|
||||
$(".projects-dialog-screen-create-row-creds").show();
|
||||
$(".projects-dialog-screen-create-row-passphrase").hide();
|
||||
$(".projects-dialog-screen-create-row-sshkey").hide();
|
||||
} else {
|
||||
$(".projects-dialog-screen-create-row-creds").show();
|
||||
$(".projects-dialog-screen-create-row-passphrase").hide();
|
||||
$(".projects-dialog-screen-create-row-sshkey").hide();
|
||||
}
|
||||
|
||||
|
||||
@ -331,6 +338,16 @@ RED.projects = (function() {
|
||||
$('<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);
|
||||
|
||||
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);
|
||||
$('<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);
|
||||
@ -397,14 +414,29 @@ RED.projects = (function() {
|
||||
projectData.copy = copyProject.name;
|
||||
} else if (projectType === 'clone') {
|
||||
// projectData.credentialSecret = projectSecretInput.val();
|
||||
var repoUrl = projectRepoInput.val();
|
||||
var metaData = {};
|
||||
if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(repoUrl)) {
|
||||
projectData.git = {
|
||||
remotes: {
|
||||
'origin': {
|
||||
url: projectRepoInput.val(),
|
||||
url: repoUrl,
|
||||
key_file: getSelectedSSHKey(projectRepoSSHKeySelect).name,
|
||||
passphrase: projectRepoPassphrase.val()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
projectData.git = {
|
||||
remotes: {
|
||||
'origin': {
|
||||
url: repoUrl,
|
||||
username: projectRepoUserInput.val(),
|
||||
password: projectRepoPasswordInput.val()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -434,6 +466,8 @@ RED.projects = (function() {
|
||||
projectRepoUserInput.addClass("input-error");
|
||||
projectRepoPasswordInput.addClass("input-error");
|
||||
// getRepoAuthDetails(req);
|
||||
projectRepoSSHKeySelect.addClass("input-error");
|
||||
projectRepoPassphrase.addClass("input-error");
|
||||
console.log("git auth error",error);
|
||||
},
|
||||
'unexpected_error': function(error) {
|
||||
@ -694,6 +728,100 @@ RED.projects = (function() {
|
||||
return container;
|
||||
}
|
||||
|
||||
// var selectedSSHKey = null;
|
||||
// var sshkeyList = null;
|
||||
$.fn.isVisible = function() {
|
||||
return $.expr.filters.visible(this[0]);
|
||||
}
|
||||
function createSSHKeyList(options) {
|
||||
options = options || {};
|
||||
var minHeight = "33px";
|
||||
var maxHeight = options.height || "120px";
|
||||
// var container = $('<div></div>',{style:"min-height: "+height+"; height: "+height+";"});
|
||||
var container = $('<div></div>',{style:"max-height: "+maxHeight+";"});
|
||||
|
||||
// var sshkeyList = $('<ol>',{class:"projects-dialog-sshkey-list", style:"height:"+height}).appendTo(container).editableList({
|
||||
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.isVisible() ) {
|
||||
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) {
|
||||
console.log('key:', 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);
|
||||
}
|
||||
console.log('container.sshkeys:', container.data('sshkeys'));
|
||||
return container;
|
||||
}
|
||||
function getSelectedSSHKey(container) {
|
||||
var selected = $.data(container[0], 'selected');
|
||||
if ( container && selected ) {
|
||||
return selected;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function refreshSSHKeyList(container) {
|
||||
console.log('refreshSSHKeyList');
|
||||
var sshkeyList = $.data(container[0], 'sshkeys');
|
||||
console.log(' ---> container:', container);
|
||||
console.log(' ---> container.sshkeyList:', sshkeyList);
|
||||
if ( container && sshkeyList ) {
|
||||
sshkeyList.empty();
|
||||
$.getJSON("settings/user/keys", function(data) {
|
||||
var keyList = $.data(container[0], 'sshkeys');
|
||||
data.keys.forEach(function(key) {
|
||||
console.log('key:', key);
|
||||
if ( keyList ) {
|
||||
keyList.editableList('addItem',key);
|
||||
}
|
||||
else {
|
||||
console.log('[refresh] Error! selectedSSHKey is not set up.');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function sendRequest(options,body) {
|
||||
// dialogBody.hide();
|
||||
console.log(options.url,body);
|
||||
@ -1013,7 +1141,9 @@ RED.projects = (function() {
|
||||
var projectsAPI = {
|
||||
sendRequest:sendRequest,
|
||||
createBranchList:createBranchList,
|
||||
addSpinnerOverlay:addSpinnerOverlay
|
||||
addSpinnerOverlay:addSpinnerOverlay,
|
||||
createSSHKeyList:createSSHKeyList,
|
||||
refreshSSHKeyList:refreshSSHKeyList
|
||||
};
|
||||
RED.projects.settings.init(projectsAPI);
|
||||
RED.projects.userSettings.init(projectsAPI);
|
||||
|
@ -654,6 +654,94 @@
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
.expandable-list-entry {
|
||||
.exandable-list-entry-header {
|
||||
|
@ -18,6 +18,7 @@
|
||||
var fs = require('fs-extra');
|
||||
var when = require('when');
|
||||
var fspath = require("path");
|
||||
var os = require('os');
|
||||
|
||||
var gitTools = require("./git");
|
||||
var util = require("../util");
|
||||
@ -680,6 +681,7 @@ function createProject(user, metadata) {
|
||||
if (metadata.git && metadata.git.remotes && metadata.git.remotes.origin) {
|
||||
var originRemote = metadata.git.remotes.origin;
|
||||
var auth;
|
||||
console.log('originRemote:', originRemote);
|
||||
if (originRemote.hasOwnProperty("username") && originRemote.hasOwnProperty("password")) {
|
||||
authCache.set(project,originRemote.url,username,{ // TODO: hardcoded remote name
|
||||
username: originRemote.username,
|
||||
@ -688,6 +690,15 @@ function createProject(user, metadata) {
|
||||
);
|
||||
auth = authCache.get(project,originRemote.url,username);
|
||||
}
|
||||
else if (originRemote.hasOwnProperty("key_file") && originRemote.hasOwnProperty("passphrase")) {
|
||||
var key_file_name = (username === '_') ? os.hostname() + '_' + 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) {
|
||||
// Check this is a valid project
|
||||
// If it is empty
|
||||
|
@ -45,7 +45,7 @@ var ResponseServer = function(auth) {
|
||||
parts.push(data.substring(0, m));
|
||||
data = data.substring(m);
|
||||
var line = parts.join("");
|
||||
console.log("LINE",line);
|
||||
console.log("LINE:",line);
|
||||
parts = [];
|
||||
if (line==='Username') {
|
||||
connection.end(auth.username);
|
||||
@ -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 = {
|
||||
ResponseServer: ResponseServer
|
||||
ResponseServer: ResponseServer,
|
||||
ResponseSSHServer: ResponseSSHServer
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ var when = require('when');
|
||||
var exec = require('child_process').exec;
|
||||
var spawn = require('child_process').spawn;
|
||||
var authResponseServer = require('./authServer').ResponseServer;
|
||||
var sshResponseServer = require('./authServer').ResponseSSHServer;
|
||||
var clone = require('clone');
|
||||
var path = require("path");
|
||||
|
||||
@ -41,6 +42,11 @@ function runGitCommand(args,cwd,env) {
|
||||
});
|
||||
|
||||
child.on('close', function(code) {
|
||||
console.log("===============================================================");
|
||||
console.log("stdout:", stdout);
|
||||
console.log("===============================================================");
|
||||
console.log("stderr:", stderr);
|
||||
console.log("===============================================================");
|
||||
if (code !== 0) {
|
||||
var err = new Error(stderr);
|
||||
err.stdout = stdout;
|
||||
@ -49,6 +55,8 @@ function runGitCommand(args,cwd,env) {
|
||||
err.code = "git_auth_failed";
|
||||
} else if(/HTTP Basic: Access denied/.test(stderr)) {
|
||||
err.code = "git_auth_failed";
|
||||
} else if(/Permission denied \(publickey\)/.test(stderr)) {
|
||||
err.code = "git_auth_failed";
|
||||
} else if(/Connection refused/.test(stderr)) {
|
||||
err.code = "git_connection_failed";
|
||||
} else if (/commit your changes or stash/.test(stderr)) {
|
||||
@ -56,8 +64,9 @@ function runGitCommand(args,cwd,env) {
|
||||
} else if (/CONFLICT/.test(err.stdout)) {
|
||||
err.code = "git_pull_merge_conflict";
|
||||
}
|
||||
|
||||
|
||||
console.log("===============================================================");
|
||||
console.log('err:', err);
|
||||
console.log("===============================================================");
|
||||
|
||||
return reject(err);
|
||||
}
|
||||
@ -78,6 +87,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) {
|
||||
if (name[0] !== '"') {
|
||||
return name;
|
||||
@ -331,7 +356,12 @@ module.exports = {
|
||||
}
|
||||
var promise;
|
||||
if (auth) {
|
||||
if ( auth.key_path ) {
|
||||
promise = runGitCommandWithSSHCommand(args,cwd,auth);
|
||||
}
|
||||
else {
|
||||
promise = runGitCommandWithAuth(args,cwd,auth);
|
||||
}
|
||||
} else {
|
||||
promise = runGitCommand(args,cwd)
|
||||
}
|
||||
@ -362,7 +392,12 @@ module.exports = {
|
||||
args.push("--porcelain");
|
||||
var promise;
|
||||
if (auth) {
|
||||
if ( auth.key_path ) {
|
||||
promise = runGitCommandWithSSHCommand(args,cwd,auth);
|
||||
}
|
||||
else {
|
||||
promise = runGitCommandWithAuth(args,cwd,auth);
|
||||
}
|
||||
} else {
|
||||
promise = runGitCommand(args,cwd)
|
||||
}
|
||||
@ -387,7 +422,12 @@ module.exports = {
|
||||
}
|
||||
args.push(".");
|
||||
if (auth) {
|
||||
if ( auth.key_path ) {
|
||||
return runGitCommandWithSSHCommand(args,cwd,auth);
|
||||
}
|
||||
else {
|
||||
return runGitCommandWithAuth(args,cwd,auth);
|
||||
}
|
||||
} else {
|
||||
return runGitCommand(args,cwd);
|
||||
}
|
||||
@ -442,7 +482,12 @@ module.exports = {
|
||||
fetch: function(cwd,remote,auth) {
|
||||
var args = ["fetch",remote];
|
||||
if (auth) {
|
||||
if ( auth.key_path ) {
|
||||
return runGitCommandWithSSHCommand(args,cwd,auth);
|
||||
}
|
||||
else {
|
||||
return runGitCommandWithAuth(args,cwd,auth);
|
||||
}
|
||||
} else {
|
||||
return runGitCommand(args,cwd);
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ function getProject(user, name) {
|
||||
return Projects.get(name).then(function(project) {
|
||||
var result = project.toJSON();
|
||||
var projectSettings = settings.get("projects").projects;
|
||||
if (projectSettings[name].git && projectSettings[name].git.user[username]) {
|
||||
if (projectSettings[name] && projectSettings[name].git && projectSettings[name].git.user[username]) {
|
||||
result.git.user = projectSettings[name].git.user[username];
|
||||
}
|
||||
return result;
|
||||
|
Loading…
Reference in New Issue
Block a user