mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Fix reauthentication of remote repositories
This commit is contained in:
parent
3c6ba72a2a
commit
9c350311e8
@ -50,15 +50,27 @@ RED.projects.userSettings = (function() {
|
|||||||
.appendTo(title)
|
.appendTo(title)
|
||||||
.click(function(evt) {
|
.click(function(evt) {
|
||||||
addKeyButton.attr('disabled',true);
|
addKeyButton.attr('disabled',true);
|
||||||
addKeyDialog.slideDown(200, function() {
|
addKeyDialog.slideDown(200);
|
||||||
// addKeyDialog[0].scrollIntoView();
|
keyNameInput.focus();
|
||||||
});
|
saveButton.attr('disabled',true);
|
||||||
});
|
});
|
||||||
|
|
||||||
var validateForm = function() {
|
var validateForm = function() {
|
||||||
var validName = /^[a-zA-Z0-9\-_]+$/.test(keyNameInput.val());
|
var validName = /^[a-zA-Z0-9\-_]+$/.test(keyNameInput.val());
|
||||||
saveButton.attr('disabled',!validName);
|
var passphrase = passphraseInput.val();
|
||||||
|
var validPassphrase = passphrase.length === 0 || passphrase.length >= 8;
|
||||||
|
|
||||||
|
saveButton.attr('disabled',!validName || !validPassphrase);
|
||||||
keyNameInput.toggleClass('input-error',keyNameInputChanged&&!validName);
|
keyNameInput.toggleClass('input-error',keyNameInputChanged&&!validName);
|
||||||
|
passphraseInput.toggleClass('input-error',!validPassphrase);
|
||||||
|
if (!validPassphrase) {
|
||||||
|
passphraseInputSubLabel.text("Passphrase too short");
|
||||||
|
} else if (passphrase.length === 0) {
|
||||||
|
passphraseInputSubLabel.text("Optional");
|
||||||
|
} else {
|
||||||
|
passphraseInputSubLabel.text("");
|
||||||
|
}
|
||||||
|
|
||||||
if (popover) {
|
if (popover) {
|
||||||
popover.close();
|
popover.close();
|
||||||
popover = null;
|
popover = null;
|
||||||
@ -68,8 +80,8 @@ RED.projects.userSettings = (function() {
|
|||||||
var row = $('<div class="user-settings-row"></div>').appendTo(container);
|
var row = $('<div class="user-settings-row"></div>').appendTo(container);
|
||||||
var addKeyDialog = $('<div class="projects-dialog-list-dialog"></div>').hide().appendTo(row);
|
var addKeyDialog = $('<div class="projects-dialog-list-dialog"></div>').hide().appendTo(row);
|
||||||
$('<div class="projects-dialog-list-dialog-header">').text('Generate SSH Key').appendTo(addKeyDialog);
|
$('<div class="projects-dialog-list-dialog-header">').text('Generate SSH Key').appendTo(addKeyDialog);
|
||||||
|
var addKeyDialogBody = $('<div>').appendTo(addKeyDialog);
|
||||||
row = $('<div class="user-settings-row"></div>').appendTo(addKeyDialog);
|
row = $('<div class="user-settings-row"></div>').appendTo(addKeyDialogBody);
|
||||||
$('<label for=""></label>').text('Name').appendTo(row);
|
$('<label for=""></label>').text('Name').appendTo(row);
|
||||||
var keyNameInput = $('<input type="text">').appendTo(row).on("change keyup paste",function() {
|
var keyNameInput = $('<input type="text">').appendTo(row).on("change keyup paste",function() {
|
||||||
keyNameInputChanged = true;
|
keyNameInputChanged = true;
|
||||||
@ -78,10 +90,10 @@ RED.projects.userSettings = (function() {
|
|||||||
var keyNameInputChanged = false;
|
var keyNameInputChanged = false;
|
||||||
$('<label class="projects-edit-form-sublabel"><small>Must contain only A-Z 0-9 _ -</small></label>').appendTo(row).find("small");
|
$('<label class="projects-edit-form-sublabel"><small>Must contain only A-Z 0-9 _ -</small></label>').appendTo(row).find("small");
|
||||||
|
|
||||||
row = $('<div class="user-settings-row"></div>').appendTo(addKeyDialog);
|
row = $('<div class="user-settings-row"></div>').appendTo(addKeyDialogBody);
|
||||||
$('<label for=""></label>').text('Passphrase').appendTo(row);
|
$('<label for=""></label>').text('Passphrase').appendTo(row);
|
||||||
passphraseInput = $('<input type="password">').appendTo(row).on("change keyup paste",validateForm);
|
passphraseInput = $('<input type="password">').appendTo(row).on("change keyup paste",validateForm);
|
||||||
$('<label class="projects-edit-form-sublabel"><small>Optional</small></label>').appendTo(row).find("small");
|
var passphraseInputSubLabel = $('<label class="projects-edit-form-sublabel"><small>Optional</small></label>').appendTo(row).find("small");
|
||||||
|
|
||||||
var hideEditForm = function() {
|
var hideEditForm = function() {
|
||||||
addKeyButton.attr('disabled',false);
|
addKeyButton.attr('disabled',false);
|
||||||
@ -128,7 +140,7 @@ RED.projects.userSettings = (function() {
|
|||||||
done(error);
|
done(error);
|
||||||
},
|
},
|
||||||
200: function(data) {
|
200: function(data) {
|
||||||
refreshSSHKeyList();
|
refreshSSHKeyList(payload.name);
|
||||||
done();
|
done();
|
||||||
},
|
},
|
||||||
400: {
|
400: {
|
||||||
@ -166,7 +178,7 @@ RED.projects.userSettings = (function() {
|
|||||||
utils.sendRequest(options);
|
utils.sendRequest(options);
|
||||||
|
|
||||||
var formButtons = $('<span class="button-row" style="position: relative; float: right; margin: 10px;"></span>').appendTo(row);
|
var formButtons = $('<span class="button-row" style="position: relative; float: right; margin: 10px;"></span>').appendTo(row);
|
||||||
$('<button class="editor-button editor-button-small">Copy to Clipboard</button>')
|
$('<button class="editor-button editor-button-small">Copy to clipboard</button>')
|
||||||
.appendTo(formButtons)
|
.appendTo(formButtons)
|
||||||
.click(function(evt) {
|
.click(function(evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
@ -258,10 +270,13 @@ RED.projects.userSettings = (function() {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
if (entry.expand) {
|
||||||
|
expandedRow = expandKey(container,entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var refreshSSHKeyList = function() {
|
var refreshSSHKeyList = function(justAdded) {
|
||||||
$.getJSON("settings/user/keys",function(result) {
|
$.getJSON("settings/user/keys",function(result) {
|
||||||
if (result.keys) {
|
if (result.keys) {
|
||||||
result.keys.sort(function(A,B) {
|
result.keys.sort(function(A,B) {
|
||||||
@ -269,6 +284,9 @@ RED.projects.userSettings = (function() {
|
|||||||
});
|
});
|
||||||
keyList.editableList('empty');
|
keyList.editableList('empty');
|
||||||
result.keys.forEach(function(key) {
|
result.keys.forEach(function(key) {
|
||||||
|
if (key.name === justAdded) {
|
||||||
|
key.expand = true;
|
||||||
|
}
|
||||||
keyList.editableList('addItem',key);
|
keyList.editableList('addItem',key);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -278,137 +296,10 @@ RED.projects.userSettings = (function() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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>');
|
||||||
createGitUserSection(pane);
|
createGitUserSection(pane);
|
||||||
createSSHKeySection(pane);
|
createSSHKeySection(pane);
|
||||||
|
|
||||||
createPublicKeyDialog();
|
|
||||||
return pane;
|
return pane;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,9 +539,9 @@ RED.projects = (function() {
|
|||||||
$(".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();
|
$(".projects-dialog-screen-create-row-sshkey").show();
|
||||||
if ( !getSelectedSSHKey(projectRepoSSHKeySelect) ) {
|
// if ( !getSelectedSSHKey(projectRepoSSHKeySelect) ) {
|
||||||
valid = false;
|
// 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();
|
||||||
@ -576,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,14 +757,21 @@ RED.projects = (function() {
|
|||||||
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);
|
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({
|
$('<label for="projects-dialog-screen-create-project-repo-passphrase">SSH Key</label>').appendTo(row);
|
||||||
height: "120px",
|
projectRepoSSHKeySelect = $("<select>").appendTo(row);
|
||||||
selectAction: function(entry, header) {
|
|
||||||
$('.projects-dialog-sshkey-list-entry').removeClass('selected');
|
$.getJSON("settings/user/keys", function(data) {
|
||||||
header.addClass('selected');
|
var count = 0;
|
||||||
|
data.keys.forEach(function(key) {
|
||||||
|
projectRepoSSHKeySelect.append($("<option></option>").val(key.name).text(key.name));
|
||||||
|
count++;
|
||||||
|
});
|
||||||
|
if (count === 0) {
|
||||||
|
// projectRepoSSHKeySelect
|
||||||
}
|
}
|
||||||
}).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);
|
||||||
@ -838,17 +845,17 @@ RED.projects = (function() {
|
|||||||
var repoUrl = projectRepoInput.val();
|
var repoUrl = projectRepoInput.val();
|
||||||
var metaData = {};
|
var metaData = {};
|
||||||
if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(repoUrl)) {
|
if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(repoUrl)) {
|
||||||
var selected = getSelectedSSHKey(projectRepoSSHKeySelect);
|
var selected = projectRepoSSHKeySelect.val();//false;//getSelectedSSHKey(projectRepoSSHKeySelect);
|
||||||
if ( selected && selected.name ) {
|
if ( selected ) {
|
||||||
projectData.git = {
|
projectData.git = {
|
||||||
remotes: {
|
remotes: {
|
||||||
'origin': {
|
'origin': {
|
||||||
url: repoUrl,
|
url: repoUrl,
|
||||||
key_file: selected.name,
|
key_file: selected,
|
||||||
passphrase: projectRepoPassphrase.val()
|
passphrase: projectRepoPassphrase.val()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log("Error! Can't get selected SSH key path.");
|
console.log("Error! Can't get selected SSH key path.");
|
||||||
@ -1156,86 +1163,8 @@ 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();
|
||||||
@ -1306,12 +1235,36 @@ RED.projects = (function() {
|
|||||||
return;
|
return;
|
||||||
} else if (options.handleAuthFail !== false && xhr.responseJSON.error === 'git_auth_failed') {
|
} else if (options.handleAuthFail !== false && xhr.responseJSON.error === 'git_auth_failed') {
|
||||||
var url = activeProject.git.remotes[options.remote||'origin'].fetch;
|
var url = activeProject.git.remotes[options.remote||'origin'].fetch;
|
||||||
|
|
||||||
var message = $('<div>'+
|
var message = $('<div>'+
|
||||||
'<div class="form-row">Authentication required for repository:</div>'+
|
'<div class="form-row">Authentication required for repository:</div>'+
|
||||||
'<div class="form-row"><div style="margin-left: 20px;">'+url+'</div></div>'+
|
'<div class="form-row"><div style="margin-left: 20px;">'+url+'</div></div>'+
|
||||||
'<div class="form-row"><label for="projects-user-auth-username">Username</label><input id="projects-user-auth-username" type="text"></input></div>'+
|
|
||||||
'<div class="form-row"><label for=projects-user-auth-password">Password</label><input id="projects-user-auth-password" type="password"></input></div>'+
|
|
||||||
'</div>');
|
'</div>');
|
||||||
|
|
||||||
|
var isSSH = false;
|
||||||
|
if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(url)) {
|
||||||
|
isSSH = true;
|
||||||
|
var row = $('<div class="form-row"></div>').appendTo(message);
|
||||||
|
$('<label for="projects-user-auth-key">SSH Key</label>').appendTo(row);
|
||||||
|
var projectRepoSSHKeySelect = $('<select id="projects-user-auth-key">').width('70%').appendTo(row);
|
||||||
|
$.getJSON("settings/user/keys", function(data) {
|
||||||
|
var count = 0;
|
||||||
|
data.keys.forEach(function(key) {
|
||||||
|
projectRepoSSHKeySelect.append($("<option></option>").val(key.name).text(key.name));
|
||||||
|
count++;
|
||||||
|
});
|
||||||
|
if (count === 0) {
|
||||||
|
// projectRepoSSHKeySelect
|
||||||
|
}
|
||||||
|
});
|
||||||
|
row = $('<div class="form-row"></div>').appendTo(message);
|
||||||
|
$('<label for="projects-user-auth-passphrase">Passphrase</label>').appendTo(row);
|
||||||
|
$('<input id="projects-user-auth-passphrase" type="password"></input>').appendTo(row);
|
||||||
|
} else {
|
||||||
|
$('<div class="form-row"><label for="projects-user-auth-username">Username</label><input id="projects-user-auth-username" type="text"></input></div>'+
|
||||||
|
'<div class="form-row"><label for=projects-user-auth-password">Password</label><input id="projects-user-auth-password" type="password"></input></div>').appendTo(message);
|
||||||
|
}
|
||||||
|
|
||||||
var notification = RED.notify(message,{
|
var notification = RED.notify(message,{
|
||||||
type:"error",
|
type:"error",
|
||||||
fixed: true,
|
fixed: true,
|
||||||
@ -1327,14 +1280,15 @@ RED.projects = (function() {
|
|||||||
},{
|
},{
|
||||||
text: $('<span><i class="fa fa-refresh"></i> Retry</span>'),
|
text: $('<span><i class="fa fa-refresh"></i> Retry</span>'),
|
||||||
click: function() {
|
click: function() {
|
||||||
var username = $('#projects-user-auth-username').val();
|
|
||||||
var password = $('#projects-user-auth-password').val();
|
|
||||||
body = body || {};
|
body = body || {};
|
||||||
var authBody = {git:{remotes:{}}};
|
var authBody = {};
|
||||||
authBody.git.remotes[options.remote||'origin'] = {
|
if (isSSH) {
|
||||||
username: username,
|
authBody.keyFile = $('#projects-user-auth-key').val();
|
||||||
password: password
|
authBody.passphrase = $('#projects-user-auth-passphrase').val();
|
||||||
};
|
} else {
|
||||||
|
authBody.username = $('#projects-user-auth-username').val();
|
||||||
|
authBody.password = $('#projects-user-auth-password').val();
|
||||||
|
}
|
||||||
var done = function(err) {
|
var done = function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log("Failed to update auth");
|
console.log("Failed to update auth");
|
||||||
@ -1346,7 +1300,7 @@ RED.projects = (function() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
sendRequest({
|
sendRequest({
|
||||||
url: "projects/"+activeProject.name,
|
url: "projects/"+activeProject.name+"/remotes/"+(options.remote||'origin'),
|
||||||
type: "PUT",
|
type: "PUT",
|
||||||
responses: {
|
responses: {
|
||||||
0: function(error) {
|
0: function(error) {
|
||||||
@ -1361,7 +1315,7 @@ RED.projects = (function() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},authBody);
|
},{auth:authBody});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -1553,9 +1507,7 @@ 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);
|
||||||
|
@ -816,6 +816,7 @@ div.projects-dialog-ssh-public-key {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.projects-dialog-list-dialog {
|
.projects-dialog-list-dialog {
|
||||||
|
position: relative;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
background: white;
|
background: white;
|
||||||
|
@ -512,6 +512,23 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update a remote
|
||||||
|
app.put("/:id/remotes/:remoteName", needsPermission("projects.write"), function(req,res) {
|
||||||
|
var projectName = req.params.id;
|
||||||
|
var remoteName = req.params.remoteName;
|
||||||
|
runtime.storage.projects.updateRemote(req.user, projectName, remoteName, req.body).then(function(data) {
|
||||||
|
res.status(204).end();
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
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;
|
return app;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,12 +63,15 @@ module.exports = {
|
|||||||
// console.log('username:', username);
|
// console.log('username:', username);
|
||||||
runtime.storage.sshkeys.getSSHKey(username, req.params.id)
|
runtime.storage.sshkeys.getSSHKey(username, req.params.id)
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
res.json({
|
if (data) {
|
||||||
publickey: data
|
res.json({
|
||||||
});
|
publickey: data
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.status(404).end();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
console.log(err.stack);
|
|
||||||
if (err.code) {
|
if (err.code) {
|
||||||
res.status(400).json({error:err.code, message: err.message});
|
res.status(400).json({error:err.code, message: err.message});
|
||||||
} else {
|
} else {
|
||||||
@ -90,7 +93,6 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
console.log(err.stack);
|
|
||||||
if (err.code) {
|
if (err.code) {
|
||||||
res.status(400).json({error:err.code, message: err.message});
|
res.status(400).json({error:err.code, message: err.message});
|
||||||
} else {
|
} else {
|
||||||
@ -107,11 +109,10 @@ module.exports = {
|
|||||||
app.delete("/:id", needsPermission("settings.write"), function(req,res) {
|
app.delete("/:id", needsPermission("settings.write"), function(req,res) {
|
||||||
var username = getUsername(req.user);
|
var username = getUsername(req.user);
|
||||||
runtime.storage.sshkeys.deleteSSHKey(username, req.params.id)
|
runtime.storage.sshkeys.deleteSSHKey(username, req.params.id)
|
||||||
.then(function(ret) {
|
.then(function() {
|
||||||
res.status(204).end();
|
res.status(204).end();
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
console.log(err.stack);
|
|
||||||
if (err.code) {
|
if (err.code) {
|
||||||
res.status(400).json({error:err.code, message: err.message});
|
res.status(400).json({error:err.code, message: err.message});
|
||||||
} else {
|
} else {
|
||||||
|
@ -120,12 +120,14 @@ Project.prototype.loadRemotes = function() {
|
|||||||
}).then(function() {
|
}).then(function() {
|
||||||
var allRemotes = Object.keys(project.remotes);
|
var allRemotes = Object.keys(project.remotes);
|
||||||
var match = "";
|
var match = "";
|
||||||
allRemotes.forEach(function(remote) {
|
if (project.branches.remote) {
|
||||||
if (project.branches.remote.indexOf(remote) === 0 && match.length < remote.length) {
|
allRemotes.forEach(function(remote) {
|
||||||
match = remote;
|
if (project.branches.remote.indexOf(remote) === 0 && match.length < remote.length) {
|
||||||
}
|
match = remote;
|
||||||
});
|
}
|
||||||
project.currentRemote = project.parseRemoteBranch(project.branches.remote).remote;
|
});
|
||||||
|
project.currentRemote = project.parseRemoteBranch(project.branches.remote).remote;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,8 +543,21 @@ Project.prototype.addRemote = function(user,remote,options) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
Project.prototype.updateRemote = function(user,remote,options) {
|
Project.prototype.updateRemote = function(user,remote,options) {
|
||||||
// TODO: once the sshkey support is added, move the updating of remotes,
|
var username;
|
||||||
// including their auth details, down here.
|
if (!user) {
|
||||||
|
username = "_";
|
||||||
|
} else {
|
||||||
|
username = user.username;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.auth) {
|
||||||
|
var url = this.remotes[remote].fetch;
|
||||||
|
if (options.auth.keyFile) {
|
||||||
|
options.auth.key_path = fspath.join(projectsDir, ".sshkeys", ((username === '_')?'__default':username) + '_' + options.auth.keyFile);
|
||||||
|
}
|
||||||
|
authCache.set(this.name,url,username,options.auth);
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
Project.prototype.removeRemote = function(user, remote) {
|
Project.prototype.removeRemote = function(user, remote) {
|
||||||
// TODO: if this was the last remote using this url, then remove the authCache
|
// TODO: if this was the last remote using this url, then remove the authCache
|
||||||
@ -764,7 +779,7 @@ 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")) {
|
else if (originRemote.hasOwnProperty("key_file") && originRemote.hasOwnProperty("passphrase")) {
|
||||||
var key_file_name = (username === '_') ? '.default' + '_' + originRemote.key_file : username + '_' + originRemote.key_file;
|
var key_file_name = (username === '_') ? '__default' + '_' + originRemote.key_file : username + '_' + originRemote.key_file;
|
||||||
authCache.set(project,originRemote.url,username,{ // TODO: hardcoded remote name
|
authCache.set(project,originRemote.url,username,{ // TODO: hardcoded remote name
|
||||||
key_path: fspath.join(projectsDir, ".sshkeys", key_file_name),
|
key_path: fspath.join(projectsDir, ".sshkeys", key_file_name),
|
||||||
passphrase: originRemote.passphrase
|
passphrase: originRemote.passphrase
|
||||||
|
@ -266,6 +266,10 @@ function removeRemote(user, project, remote) {
|
|||||||
checkActiveProject(project);
|
checkActiveProject(project);
|
||||||
return activeProject.removeRemote(user, remote);
|
return activeProject.removeRemote(user, remote);
|
||||||
}
|
}
|
||||||
|
function updateRemote(user, project, remote, body) {
|
||||||
|
checkActiveProject(project);
|
||||||
|
return activeProject.updateRemote(user, remote, body);
|
||||||
|
}
|
||||||
|
|
||||||
function getActiveProject(user) {
|
function getActiveProject(user) {
|
||||||
return activeProject;
|
return activeProject;
|
||||||
@ -491,6 +495,7 @@ module.exports = {
|
|||||||
getRemotes: getRemotes,
|
getRemotes: getRemotes,
|
||||||
addRemote: addRemote,
|
addRemote: addRemote,
|
||||||
removeRemote: removeRemote,
|
removeRemote: removeRemote,
|
||||||
|
updateRemote: updateRemote,
|
||||||
|
|
||||||
getFlows: getFlows,
|
getFlows: getFlows,
|
||||||
saveFlows: saveFlows,
|
saveFlows: saveFlows,
|
||||||
|
@ -80,6 +80,8 @@ function getSSHKey(username, name) {
|
|||||||
return checkSSHKeyFileAndGetPublicKeyFileName(username, name)
|
return checkSSHKeyFileAndGetPublicKeyFileName(username, name)
|
||||||
.then(function(publicSSHKeyPath) {
|
.then(function(publicSSHKeyPath) {
|
||||||
return fs.readFile(publicSSHKeyPath, 'utf-8');
|
return fs.readFile(publicSSHKeyPath, 'utf-8');
|
||||||
|
}).catch(function() {
|
||||||
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,29 +91,32 @@ function generateSSHKey(username, options) {
|
|||||||
return checkExistSSHKeyFiles(username, name)
|
return checkExistSSHKeyFiles(username, name)
|
||||||
.then(function(result) {
|
.then(function(result) {
|
||||||
if ( result ) {
|
if ( result ) {
|
||||||
throw new Error('Some SSH Keyfile exists');
|
var e = new Error("SSH Key name exists");
|
||||||
}
|
e.code = "key_exists";
|
||||||
else {
|
throw e;
|
||||||
|
} else {
|
||||||
var comment = options.comment || "";
|
var comment = options.comment || "";
|
||||||
var password = options.password || "";
|
var password = options.password || "";
|
||||||
|
if (password.length > 0 && password.length < 5) {
|
||||||
|
var e2 = new Error("SSH Key passphrase too short");
|
||||||
|
e2.code = "key_passphrase_too_short";
|
||||||
|
throw e2;
|
||||||
|
}
|
||||||
var size = options.size || 2048;
|
var size = options.size || 2048;
|
||||||
var sshKeyFileBasename = username + '_' + name;
|
var sshKeyFileBasename = username + '_' + name;
|
||||||
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||||
return generateSSHKeyPair(privateKeyFilePath, comment, password, size)
|
return generateSSHKeyPair(name, privateKeyFilePath, comment, password, size)
|
||||||
.then(function() {
|
|
||||||
return name;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(function(keyfile_name) {
|
// .then(function(keyfile_name) {
|
||||||
return checkSSHKeyFileAndGetPublicKeyFileName(username, name)
|
// return checkSSHKeyFileAndGetPublicKeyFileName(username, name)
|
||||||
.then(function() {
|
// .then(function() {
|
||||||
return keyfile_name;
|
// return keyfile_name;
|
||||||
})
|
// })
|
||||||
.catch(function() {
|
// .catch(function(err) {
|
||||||
throw new Error('Failed to generate ssh key files');
|
// throw new Error('Failed to generate ssh key files');
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteSSHKey(username, name) {
|
function deleteSSHKey(username, name) {
|
||||||
@ -125,7 +130,7 @@ function checkExistSSHKeyFiles(username, name) {
|
|||||||
var sshKeyFileBasename = username + '_' + name;
|
var sshKeyFileBasename = username + '_' + name;
|
||||||
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||||
var publicKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename + '.pub');
|
var publicKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename + '.pub');
|
||||||
return Promise.race([
|
return Promise.all([
|
||||||
fs.access(privateKeyFilePath, (fs.constants || fs).R_OK),
|
fs.access(privateKeyFilePath, (fs.constants || fs).R_OK),
|
||||||
fs.access(publicKeyFilePath , (fs.constants || fs).R_OK)
|
fs.access(publicKeyFilePath , (fs.constants || fs).R_OK)
|
||||||
])
|
])
|
||||||
@ -157,13 +162,11 @@ function deleteSSHKeyFiles(username, name) {
|
|||||||
return Promise.all([
|
return Promise.all([
|
||||||
fs.remove(privateKeyFilePath),
|
fs.remove(privateKeyFilePath),
|
||||||
fs.remove(publicKeyFilePath)
|
fs.remove(publicKeyFilePath)
|
||||||
])
|
]);
|
||||||
.then(function(retArray) {
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateSSHKeyPair(privateKeyPath, comment, password, size) {
|
function generateSSHKeyPair(name, privateKeyPath, comment, password, size) {
|
||||||
|
log.trace("ssh-keygen["+[name,privateKeyPath,comment,size,"hasPassword?"+!!password].join(",")+"]");
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
keygen({
|
keygen({
|
||||||
location: privateKeyPath,
|
location: privateKeyPath,
|
||||||
@ -172,10 +175,11 @@ function generateSSHKeyPair(privateKeyPath, comment, password, size) {
|
|||||||
size: size
|
size: size
|
||||||
}, function(err, out) {
|
}, function(err, out) {
|
||||||
if ( err ) {
|
if ( err ) {
|
||||||
|
err.code = "key_generation_failed";
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resolve();
|
resolve(name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -151,6 +151,18 @@ describe("api/editor/sshkeys", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys/<key_file_name> --- return 404', function(done) {
|
||||||
|
mockRuntime.storage.sshkeys.getSSHKey.returns(Promise.resolve(null));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys/NOT_REAL")
|
||||||
|
.expect(404)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
it('GET /settings/user/keys --- return Unexpected Error', function(done) {
|
it('GET /settings/user/keys --- return Unexpected Error', function(done) {
|
||||||
var errInstance = new Error("Messages.....");
|
var errInstance = new Error("Messages.....");
|
||||||
mockRuntime.storage.sshkeys.listSSHKeys.returns(Promise.reject(errInstance));
|
mockRuntime.storage.sshkeys.listSSHKeys.returns(Promise.reject(errInstance));
|
||||||
|
Loading…
Reference in New Issue
Block a user