1
0
mirror of https://github.com/QRouland/UTPass.git synced 2025-07-09 05:12:29 +00:00

Add support for ssh clone

This commit is contained in:
2025-02-21 15:50:27 +01:00
parent 5683db69c7
commit 884488b9ed
16 changed files with 558 additions and 184 deletions

View File

@ -0,0 +1,149 @@
import Git 1.0
import Lomiri.Components 1.3
import Pass 1.0
import Utils 1.0
import QtQuick 2.4
Column {
property alias importSshPrivKeyButton : repoImportPrivKeyButton
property alias importSshPubKeyButton : repoImportPubKeyButton
property alias deleteSshPrivKeyButton : repoDeletePrivKeyButton
property alias deleteSshPubKeyButton : repoDeletePubKeyButton
property bool __sshPrivKeyAvailable : false
property bool __sshPubKeyAvailable : false
signal repoUrlChanged(string url)
function setRepoUrl(url) {
repoUrlInput.text = url;
}
function update() {
__sshPrivKeyAvailable = Utils.fileExists(Git.privKey);
__sshPubKeyAvailable = Utils.fileExists(Git.pubKey);
}
Component.onCompleted: {
update();
}
anchors.top: parent.fill
spacing: units.gu(1)
Text {
id: repoUrlLabel
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
width: parent.width
text: i18n.tr('Repo Url')
color: theme.palette.normal.backgroundText
}
TextField {
id: repoUrlInput
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
width: parent.width
placeholderText: "<username>@<hostname>"
onTextChanged: repoUrlChanged(repoUrlInput.text)
}
Text {
id: repoPrivKeyLabel
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
width: parent.width
text: i18n.tr('SSH private key')
color: theme.palette.normal.backgroundText
}
Button {
id: repoImportPrivKeyButton
width: parent.width
color: theme.palette.normal.positive
text: i18n.tr('Import SSH private key')
visible: !__sshPrivKeyAvailable
}
Button {
id: repoDeletePrivKeyButton
width: parent.width
color: theme.palette.normal.negative
text: i18n.tr('Delete SSH private key')
visible: __sshPrivKeyAvailable
}
Text {
id: repoPubKeyLabel
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
width: parent.width
text: i18n.tr('SSH public key')
color: theme.palette.normal.backgroundText
}
Button {
id: repoDeletePubKeyButton
width: parent.width
color: theme.palette.normal.negative
text: i18n.tr('Delete SSH public key')
visible: __sshPrivKeyAvailable
}
Button {
id: repoImportPubKeyButton
width: parent.width
color: theme.palette.normal.positive
text: i18n.tr('Import SSH public key')
visible: !__sshPrivKeyAvailable
}
Text {
id: repoPassphraseLabel
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
width: parent.width
text: i18n.tr('Passphrase')
color: theme.palette.normal.backgroundText
}
TextField {
id: repoPassphraseInput
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
width: parent.width
echoMode: TextInput.Password
placeholderText: i18n.tr('Passphrase')
}
Rectangle {
width: parent.width
height: units.gu(1)
color: theme.palette.normal.background
}
Button {
id: buttonClone
width: parent.width
color: theme.palette.normal.positive
text: i18n.tr('Clone')
onClicked: {
Git.cloneSSHKey(repoUrlInput.text, Pass.Passphrase_store, repoPassphraseInput.text);
}
}
}

View File

@ -0,0 +1,71 @@
import "../dialogs"
import "../pages/headers"
import Lomiri.Components 1.3
import Lomiri.Components.Popups 1.3
import Lomiri.Content 1.3
import Pass 1.0
import QtQuick 2.4
import Utils 1.0
Page {
id: importKeyFilePage
property var activeTransfer
property alias contentPicker : contentPicker
property alias dialogImportKeyPageError : dialogImportKeyPageError
property alias dialogImportKeyPageSucess : dialogImportKeyPageSucess
property string headerTitle : i18n.tr("Import succeeded !")
property string dialogErrorTxt : i18n.tr("Import failed !")
property string dialogSuccessTxt : i18n.tr("File Import")
ContentPeerPicker {
id: contentPicker
anchors.top: importKeyHeader.bottom
anchors.bottom: parent.bottom
anchors.topMargin: importKeyFilePage.header.height
width: parent.width
visible: parent.visible
showTitle: false
contentType: ContentType.Text
handler: ContentHandler.Source
onCancelPressed: {
pageStack.pop();
}
}
ContentTransferHint {
id: transferHint
anchors.fill: parent
activeTransfer: importKeyFilePage.activeTransfer
}
Component {
id: dialogImportKeyPageError
ErrorDialog {
textError: importKeyFilePage.dialogErrorTxt
}
}
Component {
id: dialogImportKeyPageSucess
SuccessDialog {
textSuccess: importKeyFilePage.dialogSuccessTxt
onDialogClosed: {
pageStack.pop();
}
}
}
header: StackHeader {
id: importKeyHeader
title: importKeyFilePage.headerTitle
}
}

View File

@ -19,6 +19,7 @@ Page {
for (var i = 0; i < __passwords.length; i++) {
if (__passwords[i].toUpperCase().indexOf(filter.toUpperCase()) > -1)
ret.push(__passwords[i]);
}
}
return ret;
@ -179,6 +180,7 @@ Page {
Timer {
id: searchTimer
interval: 500
onTriggered: __searchUpdateModel()
}

View File

@ -2,11 +2,12 @@ import Lomiri.Components 1.3
import QtQuick 2.4
PageHeader {
//property alias searchBarText: searchBar.text
//signal searchBarTextChanged(string text)
id: mainHeader
property alias searchBar: searchBar
//property alias searchBarText: searchBar.text
//signal searchBarTextChanged(string text)
width: parent.width
height: units.gu(6)
@ -20,9 +21,9 @@ PageHeader {
onTriggered: {
searchBar.visible = !searchBar.visible;
labelTitle.visible = !searchBar.visible;
if (searchBar.visible === true) {
if (searchBar.visible === true)
searchBar.focus = true;
}
}
},
Action {

View File

@ -90,7 +90,7 @@ Page {
header: StackHeader {
id: deleteRepoPageHeader
title: i18n.tr('Info Keys')
title: i18n.tr('Delete Password Store')
}
}

View File

@ -8,20 +8,28 @@ import Lomiri.Components.Pickers 1.3
import Lomiri.Components.Popups 1.3
import Pass 1.0
import QtQuick 2.4
import Utils 1.0
Page {
id: importGitClonePage
property int __gitModeHTTP : 0
property int __gitModeHTTP_AUTH : 1
property int __gitModeSSH_KEY : 2
property string __repoUrl
function __loadForm() {
switch (combo.selectedIndex) {
case 0:
importGitCloneForm.source = Qt.resolvedUrl("../../components/GitCloneHttp.qml");
break;
case 1:
importGitCloneForm.source = Qt.resolvedUrl("../../components/GitCloneHttpAuth.qml");
break;
case __gitModeHTTP:
importGitCloneForm.source = Qt.resolvedUrl("../../components/GitCloneHttp.qml");
break;
case __gitModeHTTP_AUTH:
importGitCloneForm.source = Qt.resolvedUrl("../../components/GitCloneHttpAuth.qml");
break;
case __gitModeSSH_KEY:
importGitCloneForm.source = Qt.resolvedUrl("../../components/GitCloneSshKey.qml");
break;
}
}
@ -29,6 +37,10 @@ Page {
Git.cloneSucceed.connect(function() {
GitSettings.type = combo.selectedIndex;
GitSettings.repoUrl = importGitClonePage.__repoUrl;
if(GitSettings.type != __gitModeSSH_KEY) { // ensure there no ssh key is kept if swicthing to another git mode
Utils.rmFile(Git.privKey);
Utils.rmFile(Git.pubKey);
}
PopupUtils.open(dialogGitCloneSuccess);
});
Git.cloneFailed.connect(function() {
@ -64,7 +76,7 @@ Page {
id: combo
width: parent.width
model: ["HTTP", "HTTP AUTH"]
model: ["HTTP", "HTTP AUTH", "SSH KEY"]
onDelegateClicked: function(i) {
timer.setTimeout(function() {
__loadForm();
@ -98,6 +110,25 @@ Page {
importGitClonePage.__repoUrl = url;
});
importGitCloneForm.item.setRepoUrl(importGitClonePage.__repoUrl);
switch (combo.selectedIndex) {
case __gitModeHTTP:
break;
case __gitModeHTTP_AUTH:
break;
case __gitModeSSH_KEY:
importGitCloneForm.item.importSshPrivKeyButton.clicked.connect(function() {
pageStack.push(Qt.resolvedUrl("ImportSSHkey.qml"), {
"isPrivateKey": true
});
});
importGitCloneForm.item.importSshPubKeyButton.clicked.connect(function() {
pageStack.push(Qt.resolvedUrl("ImportSSHkey.qml"), {
"isPrivateKey": false
});
});
break;
}
}
}

View File

@ -1,84 +1,35 @@
import "../../dialogs"
import "../headers"
import Lomiri.Components 1.3
import Lomiri.Components.Popups 1.3
import Lomiri.Content 1.3
import "../../components"
import Pass 1.0
import QtQuick 2.4
import Utils 1.0
Page {
ImportFile {
id: importKeyFilePage
property var activeTransfer
headerTitle: i18n.tr("GPG Key Import")
dialogSuccessTxt : i18n.tr("Key successfully imported !")
dialogErrorTxt : i18n.tr("Key import failed !")
ContentPeerPicker {
anchors.top: importKeyHeader.bottom
anchors.bottom: parent.bottom
anchors.topMargin: importKeyFilePage.header.height
width: parent.width
visible: parent.visible
showTitle: false
contentType: ContentType.Text
handler: ContentHandler.Source
onPeerSelected: {
peer.selectionType = ContentTransfer.Single;
importKeyFilePage.activeTransfer = peer.request();
importKeyFilePage.activeTransfer.stateChanged.connect(function() {
if (importKeyFilePage.activeTransfer.state === ContentTransfer.Charged) {
console.log("Charged");
console.log(importKeyFilePage.activeTransfer.items[0].url);
var status = Pass.importGPGKey(importKeyFilePage.activeTransfer.items[0].url);
Pass.importGPGKeySucceed.connect(function() {
Utils.rmFile(importKeyFilePage.activeTransfer.items[0].url);
importKeyFilePage.activeTransfer = null;
PopupUtils.open(dialogImportKeyPageSucess);
});
Pass.importGPGKeyFailed.connect(function(message) {
Utils.rmFile(importKeyFilePage.activeTransfer.items[0].url);
importKeyFilePage.activeTransfer = null;
PopupUtils.open(dialogImportKeyPageError);
});
}
});
}
onCancelPressed: {
pageStack.pop();
}
contentPicker.onPeerSelected: {
{
peer.selectionType = ContentTransfer.Single;
importKeyFilePage.activeTransfer = peer.request();
importKeyFilePage.activeTransfer.stateChanged.connect(function() {
if (importKeyFilePage.activeTransfer.state === ContentTransfer.Charged) {
console.log("Charged");
console.log(importKeyFilePage.activeTransfer.items[0].url);
Pass.importGPGKey(importKeyFilePage.activeTransfer.items[0].url);
Pass.importGPGKeySucceed.connect(function() {
Utils.rmFile(importKeyFilePage.activeTransfer.items[0].url);
importKeyFilePage.activeTransfer = null;
PopupUtils.open(importKeyFilePage.dialogImportKeyPageSucess);
});
Pass.importGPGKeyFailed.connect(function(message) {
Utils.rmFile(importKeyFilePage.activeTransfer.items[0].url);
importKeyFilePage.activeTransfer = null;
PopupUtils.open(importKeyFilePage.dialogImportKeyPageError);
});
}
});
}
}
ContentTransferHint {
id: transferHint
anchors.fill: parent
activeTransfer: importKeyFilePage.activeTransfer
}
Component {
id: dialogImportKeyPageError
ErrorDialog {
textError: i18n.tr("Key import failed !")
}
}
Component {
id: dialogImportKeyPageSucess
SuccessDialog {
textSuccess: i18n.tr("Key successfully imported !")
onDialogClosed: {
pageStack.pop();
}
}
}
header: StackHeader {
id: importKeyHeader
title: i18n.tr("GPG Key Import")
}
}

View File

@ -0,0 +1,34 @@
import "../../components"
import Utils 1.0
import Git 1.0
ImportFile {
id: importSSHKeyPage
property bool isPrivateKey
headerTitle: i18n.tr("SSH Key Import")
dialogSuccessTxt : i18n.tr("SSH Key successfully imported !")
dialogErrorTxt : i18n.tr("SSH Key import failed !")
contentPicker.onPeerSelected: {
{
peer.selectionType = ContentTransfer.Single;
importSSHKeyPage.activeTransfer = peer.request();
importSSHKeyPage.activeTransfer.stateChanged.connect(function() {
if (importSSHKeyPage.activeTransfer.state === ContentTransfer.Charged) {
console.log("Charged");
console.log(importSSHKeyPage.activeTransfer.items[0].url);
var ret = Git.importSshKey(importSSHKeyPage.activeTransfer.items[0].url, isPrivateKey);
Utils.rmFile(importSSHKeyPage.activeTransfer.items[0].url);
importSSHKeyPage.activeTransfer = null;
if(ret) {
PopupUtils.open(importSSHKeyPage.dialogImportKeyPageSucess);
} else {
PopupUtils.open(importSSHKeyPage.dialogImportKeyPageError);
}
}
});
}
}
}