Skip to content

Commit

Permalink
Improve SSH key process. By @bigtedde (#1802)
Browse files Browse the repository at this point in the history
  • Loading branch information
bigtedde authored Sep 26, 2023
1 parent cff00ad commit 15fa46f
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 14 deletions.
12 changes: 9 additions & 3 deletions src/vorta/views/repo_tab.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,17 @@ def create_ssh_key(self):
ssh_add_window = SSHAddWindow()
self._window = ssh_add_window # For tests
ssh_add_window.setParent(self, QtCore.Qt.WindowType.Sheet)
ssh_add_window.accepted.connect(self.init_ssh)
# ssh_add_window.rejected.connect(lambda: self.sshComboBox.setCurrentIndex(0))
ssh_add_window.rejected.connect(self.init_ssh)
ssh_add_window.failure.connect(self.create_ssh_key_failure)
ssh_add_window.open()

def create_ssh_key_failure(self, exit_code):
msg = QMessageBox()
msg.setStandardButtons(QMessageBox.StandardButton.Ok)
msg.setParent(self, QtCore.Qt.WindowType.Sheet)
msg.setText(self.tr(f'Error during key generation. Exited with code {exit_code}.'))
msg.show()

def ssh_copy_to_clipboard_action(self):
msg = QMessageBox()
msg.setStandardButtons(QMessageBox.StandardButton.Ok)
Expand All @@ -223,7 +230,6 @@ def ssh_copy_to_clipboard_action(self):
"Use it to set up remote repo permissions."
)
)

else:
msg.setText(self.tr("Could not find public key."))
else:
Expand Down
16 changes: 10 additions & 6 deletions src/vorta/views/ssh_dialog.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os

from PyQt6 import uic
from PyQt6.QtCore import QProcess, Qt
from PyQt6 import QtCore, uic
from PyQt6.QtCore import QProcess, Qt, pyqtSlot
from PyQt6.QtWidgets import QApplication, QDialogButtonBox

from ..utils import get_asset
Expand All @@ -11,6 +11,8 @@


class SSHAddWindow(SSHAddBase, SSHAddUI):
failure = QtCore.pyqtSignal(int)

def __init__(self):
super().__init__()
self.setupUi(self)
Expand Down Expand Up @@ -68,15 +70,17 @@ def generate_key(self):
self.sshproc.finished.connect(self.generate_key_result)
self.sshproc.start('ssh-keygen', ['-t', format, '-b', length, '-f', output_path, '-N', ''])

def generate_key_result(self, exitCode, exitStatus):
if exitCode == 0:
@pyqtSlot(int)
def generate_key_result(self, exit_code):
if exit_code == 0:
output_path = os.path.expanduser(self.outputFileTextBox.text())
pub_key = open(output_path + '.pub').read().strip()
clipboard = QApplication.clipboard()
clipboard.setText(pub_key)
self.errors.setText(self.tr('New key was copied to clipboard and written to %s.') % output_path)
self.reject()
else:
self.errors.setText(self.tr('Error during key generation.'))
self.reject()
self.failure.emit(exit_code)

def get_values(self):
return {
Expand Down
38 changes: 33 additions & 5 deletions tests/unit/test_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,32 +131,60 @@ def test_repo_add_success(qapp, qtbot, mocker, borg_json_output):
assert tab.repoSelector.currentText() == f"{test_repo_name} - {test_repo_url}"


def test_ssh_dialog(qapp, qtbot, tmpdir):
def test_ssh_dialog_success(qapp, qtbot, mocker, tmpdir):
main = qapp.main_window
tab = main.repoTab

qtbot.mouseClick(tab.bAddSSHKey, QtCore.Qt.MouseButton.LeftButton)
ssh_dialog = tab._window

ssh_dialog_closed = mocker.spy(ssh_dialog, 'reject')
ssh_dir = tmpdir
key_tmpfile = ssh_dir.join("id_rsa-test")
pub_tmpfile = ssh_dir.join("id_rsa-test.pub")
key_tmpfile_full = os.path.join(key_tmpfile.dirname, key_tmpfile.basename)
ssh_dialog.outputFileTextBox.setText(key_tmpfile_full)
ssh_dialog.generate_key()

# Ensure new key files exist
qtbot.waitUntil(lambda: ssh_dialog.errors.text().startswith('New key was copied'), **pytest._wait_defaults)
# Ensure new key file was created
qtbot.waitUntil(lambda: ssh_dialog_closed.called, **pytest._wait_defaults)
assert len(ssh_dir.listdir()) == 2

# Ensure new key is populated in SSH combobox
mocker.patch('os.path.expanduser', return_value=str(tmpdir))
tab.init_ssh()
assert tab.sshComboBox.count() == 2

# Ensure valid keys were created
key_tmpfile_content = key_tmpfile.read()
assert key_tmpfile_content.startswith('-----BEGIN OPENSSH PRIVATE KEY-----')
pub_tmpfile_content = pub_tmpfile.read()
assert pub_tmpfile_content.startswith('ssh-ed25519')


def test_ssh_dialog_failure(qapp, qtbot, mocker, monkeypatch, tmpdir):
main = qapp.main_window
tab = main.repoTab
monkeypatch.setattr(QMessageBox, "show", lambda *args: True)
failure_message = mocker.spy(tab, "create_ssh_key_failure")

qtbot.mouseClick(tab.bAddSSHKey, QtCore.Qt.MouseButton.LeftButton)
ssh_dialog = tab._window
ssh_dir = tmpdir
key_tmpfile = ssh_dir.join("invalid///===for_testing")
key_tmpfile_full = os.path.join(key_tmpfile.dirname, key_tmpfile.basename)
ssh_dialog.outputFileTextBox.setText(key_tmpfile_full)
ssh_dialog.generate_key()
qtbot.waitUntil(lambda: ssh_dialog.errors.text().startswith('Key file already'), **pytest._wait_defaults)

qtbot.waitUntil(lambda: failure_message.called, **pytest._wait_defaults)
failure_message.assert_called_once()

# Ensure no new ney file was created
assert len(ssh_dir.listdir()) == 0

# Ensure no new key file in combo box
mocker.patch('os.path.expanduser', return_value=str(tmpdir))
tab.init_ssh()
assert tab.sshComboBox.count() == 1


def test_create(qapp, borg_json_output, mocker, qtbot):
Expand Down

0 comments on commit 15fa46f

Please sign in to comment.