mirror of
https://github.com/naruxde/revpicommander.git
synced 2025-11-08 16:43:53 +01:00
Save SSH credentials with keyring module
The keyring module will save the username and password of the SSH connection to the operating system password storage.
This commit is contained in:
1
.idea/revpicommander.iml
generated
1
.idea/revpicommander.iml
generated
@@ -4,6 +4,7 @@
|
|||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.9 (revpicommander)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.9 (revpicommander)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
|||||||
@@ -9,5 +9,4 @@ include README.md
|
|||||||
include requirements.txt
|
include requirements.txt
|
||||||
include setup.iss
|
include setup.iss
|
||||||
include setup.py
|
include setup.py
|
||||||
include stdeb.cfg
|
|
||||||
include translate.pro
|
include translate.pro
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ revpimodio2>=2.5.6
|
|||||||
zeroconf>=0.24.4
|
zeroconf>=0.24.4
|
||||||
setuptools>=65.6.3
|
setuptools>=65.6.3
|
||||||
wheel
|
wheel
|
||||||
paramiko>=2.12.0
|
paramiko>=2.12.0
|
||||||
|
keyring>=23.13.1
|
||||||
1
setup.py
1
setup.py
@@ -15,6 +15,7 @@ setup(
|
|||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
|
|
||||||
install_requires=[
|
install_requires=[
|
||||||
|
"keyring",
|
||||||
"PyQt5",
|
"PyQt5",
|
||||||
"revpimodio2",
|
"revpimodio2",
|
||||||
"zeroconf"
|
"zeroconf"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from paramiko.ssh_exception import AuthenticationException
|
|||||||
|
|
||||||
from . import proginit as pi
|
from . import proginit as pi
|
||||||
from .ssh_tunneling.server import SSHLocalTunnel
|
from .ssh_tunneling.server import SSHLocalTunnel
|
||||||
from .sshauth import SSHAuth, SSHAuthType
|
from .sshauth import SSHAuth
|
||||||
|
|
||||||
settings = QtCore.QSettings("revpimodio.org", "RevPiCommander")
|
settings = QtCore.QSettings("revpimodio.org", "RevPiCommander")
|
||||||
"""Global application settings."""
|
"""Global application settings."""
|
||||||
@@ -304,11 +304,11 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
self.xml_funcs.clear()
|
self.xml_funcs.clear()
|
||||||
self.xml_mode = -1
|
self.xml_mode = -1
|
||||||
|
|
||||||
def pyload_connect(self, settings: RevPiSettings, parent=None) -> bool:
|
def pyload_connect(self, revpi_settings: RevPiSettings, parent=None) -> bool:
|
||||||
"""
|
"""
|
||||||
Create a new connection from settings object.
|
Create a new connection from settings object.
|
||||||
|
|
||||||
:param settings: Revolution Pi saved connection settings
|
:param revpi_settings: Revolution Pi saved connection settings
|
||||||
:param parent: Qt parent window for dialog positioning
|
:param parent: Qt parent window for dialog positioning
|
||||||
:return: True, if the connection was successfully established
|
:return: True, if the connection was successfully established
|
||||||
"""
|
"""
|
||||||
@@ -322,10 +322,16 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
|
|
||||||
socket.setdefaulttimeout(2)
|
socket.setdefaulttimeout(2)
|
||||||
|
|
||||||
if settings.ssh_use_tunnel:
|
if revpi_settings.ssh_use_tunnel:
|
||||||
while True:
|
while True:
|
||||||
diag_ssh_auth = SSHAuth(SSHAuthType.PASS, parent)
|
diag_ssh_auth = SSHAuth(
|
||||||
diag_ssh_auth.username = settings.ssh_user
|
revpi_settings.ssh_user,
|
||||||
|
"{0}.{1}_{2}".format(
|
||||||
|
settings.applicationName(),
|
||||||
|
settings.organizationName(),
|
||||||
|
revpi_settings.internal_id),
|
||||||
|
parent,
|
||||||
|
)
|
||||||
if not diag_ssh_auth.exec() == QtWidgets.QDialog.Accepted:
|
if not diag_ssh_auth.exec() == QtWidgets.QDialog.Accepted:
|
||||||
self._clear_settings()
|
self._clear_settings()
|
||||||
return False
|
return False
|
||||||
@@ -333,14 +339,15 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
ssh_user = diag_ssh_auth.username
|
ssh_user = diag_ssh_auth.username
|
||||||
ssh_pass = diag_ssh_auth.password
|
ssh_pass = diag_ssh_auth.password
|
||||||
ssh_tunnel_server = SSHLocalTunnel(
|
ssh_tunnel_server = SSHLocalTunnel(
|
||||||
settings.port,
|
revpi_settings.port,
|
||||||
settings.address,
|
revpi_settings.address,
|
||||||
settings.ssh_port
|
revpi_settings.ssh_port
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
ssh_tunnel_port = ssh_tunnel_server.connect_by_credentials(ssh_user, ssh_pass)
|
ssh_tunnel_port = ssh_tunnel_server.connect_by_credentials(ssh_user, ssh_pass)
|
||||||
break
|
break
|
||||||
except AuthenticationException:
|
except AuthenticationException:
|
||||||
|
diag_ssh_auth.remove_saved_password()
|
||||||
QtWidgets.QMessageBox.critical(
|
QtWidgets.QMessageBox.critical(
|
||||||
parent, self.tr("Error"), self.tr(
|
parent, self.tr("Error"), self.tr(
|
||||||
"The combination of username and password was rejected from the SSH server.\n\n"
|
"The combination of username and password was rejected from the SSH server.\n\n"
|
||||||
@@ -360,7 +367,7 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
sp = ServerProxy("http://127.0.0.1:{0}".format(ssh_tunnel_port))
|
sp = ServerProxy("http://127.0.0.1:{0}".format(ssh_tunnel_port))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
sp = ServerProxy("http://{0}:{1}".format(settings.address, settings.port))
|
sp = ServerProxy("http://{0}:{1}".format(revpi_settings.address, revpi_settings.port))
|
||||||
|
|
||||||
# Load values and test connection to Revolution Pi
|
# Load values and test connection to Revolution Pi
|
||||||
try:
|
try:
|
||||||
@@ -371,7 +378,7 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
pi.logger.exception(e)
|
pi.logger.exception(e)
|
||||||
self.connection_error_observed.emit(str(e))
|
self.connection_error_observed.emit(str(e))
|
||||||
|
|
||||||
if not settings.ssh_use_tunnel:
|
if not revpi_settings.ssh_use_tunnel:
|
||||||
# todo: Change message, that user can use ssh
|
# todo: Change message, that user can use ssh
|
||||||
QtWidgets.QMessageBox.critical(
|
QtWidgets.QMessageBox.critical(
|
||||||
parent, self.tr("Error"), self.tr(
|
parent, self.tr("Error"), self.tr(
|
||||||
@@ -386,19 +393,19 @@ class ConnectionManager(QtCore.QThread):
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.settings = settings
|
self.settings = revpi_settings
|
||||||
self.ssh_pass = ssh_pass
|
self.ssh_pass = ssh_pass
|
||||||
self.pyload_version = pyload_version
|
self.pyload_version = pyload_version
|
||||||
self.xml_funcs = xml_funcs
|
self.xml_funcs = xml_funcs
|
||||||
self.xml_mode = xml_mode
|
self.xml_mode = xml_mode
|
||||||
|
|
||||||
with self._lck_cli:
|
with self._lck_cli:
|
||||||
socket.setdefaulttimeout(settings.timeout)
|
socket.setdefaulttimeout(revpi_settings.timeout)
|
||||||
self.ssh_tunnel_server = ssh_tunnel_server
|
self.ssh_tunnel_server = ssh_tunnel_server
|
||||||
self._cli = sp
|
self._cli = sp
|
||||||
self._cli_connect.put_nowait((
|
self._cli_connect.put_nowait((
|
||||||
"127.0.0.1" if settings.ssh_use_tunnel else settings.address,
|
"127.0.0.1" if revpi_settings.ssh_use_tunnel else revpi_settings.address,
|
||||||
ssh_tunnel_port if settings.ssh_use_tunnel else settings.port
|
ssh_tunnel_port if revpi_settings.ssh_use_tunnel else revpi_settings.port
|
||||||
))
|
))
|
||||||
|
|
||||||
self.connection_established.emit()
|
self.connection_established.emit()
|
||||||
|
|||||||
Binary file not shown.
@@ -101,62 +101,62 @@ Nicht gespeicherte Änderunen gehen verloren</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>ConnectionManager</name>
|
<name>ConnectionManager</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="504"/>
|
<location filename="../helper.py" line="511"/>
|
||||||
<source>SIMULATING</source>
|
<source>SIMULATING</source>
|
||||||
<translation>SIMULATION</translation>
|
<translation>SIMULATION</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="507"/>
|
<location filename="../helper.py" line="514"/>
|
||||||
<source>NOT CONNECTED</source>
|
<source>NOT CONNECTED</source>
|
||||||
<translation>NICHT VERBUNDEN</translation>
|
<translation>NICHT VERBUNDEN</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="524"/>
|
<location filename="../helper.py" line="531"/>
|
||||||
<source>SERVER ERROR</source>
|
<source>SERVER ERROR</source>
|
||||||
<translation>SERVER FEHLER</translation>
|
<translation>SERVER FEHLER</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="549"/>
|
<location filename="../helper.py" line="556"/>
|
||||||
<source>RUNNING</source>
|
<source>RUNNING</source>
|
||||||
<translation>LÄUFT</translation>
|
<translation>LÄUFT</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="551"/>
|
<location filename="../helper.py" line="558"/>
|
||||||
<source>PLC FILE NOT FOUND</source>
|
<source>PLC FILE NOT FOUND</source>
|
||||||
<translation>SPS PROGRAMM NICHT GEFUNDEN</translation>
|
<translation>SPS PROGRAMM NICHT GEFUNDEN</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="553"/>
|
<location filename="../helper.py" line="560"/>
|
||||||
<source>NOT RUNNING (NO STATUS)</source>
|
<source>NOT RUNNING (NO STATUS)</source>
|
||||||
<translation>LÄUFT NICHT (KEIN STATUS)</translation>
|
<translation>LÄUFT NICHT (KEIN STATUS)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="555"/>
|
<location filename="../helper.py" line="562"/>
|
||||||
<source>PROGRAM KILLED</source>
|
<source>PROGRAM KILLED</source>
|
||||||
<translation>PROGRAMM GETÖTET</translation>
|
<translation>PROGRAMM GETÖTET</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="557"/>
|
<location filename="../helper.py" line="564"/>
|
||||||
<source>PROGRAM TERMED</source>
|
<source>PROGRAM TERMED</source>
|
||||||
<translation>PROGRAMM BEENDET</translation>
|
<translation>PROGRAMM BEENDET</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="559"/>
|
<location filename="../helper.py" line="566"/>
|
||||||
<source>NOT RUNNING</source>
|
<source>NOT RUNNING</source>
|
||||||
<translation>LÄUFT NICHT</translation>
|
<translation>LÄUFT NICHT</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="561"/>
|
<location filename="../helper.py" line="568"/>
|
||||||
<source>FINISHED WITH CODE {0}</source>
|
<source>FINISHED WITH CODE {0}</source>
|
||||||
<translation>BEENDET MIT CODE {0}</translation>
|
<translation>BEENDET MIT CODE {0}</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="376"/>
|
<location filename="../helper.py" line="383"/>
|
||||||
<source>Error</source>
|
<source>Error</source>
|
||||||
<translation>Fehler</translation>
|
<translation>Fehler</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="344"/>
|
<location filename="../helper.py" line="351"/>
|
||||||
<source>The combination of username and password was rejected from the SSH server.
|
<source>The combination of username and password was rejected from the SSH server.
|
||||||
|
|
||||||
Try again.</source>
|
Try again.</source>
|
||||||
@@ -165,7 +165,7 @@ Try again.</source>
|
|||||||
Bitte erneut versuchen.</translation>
|
Bitte erneut versuchen.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="353"/>
|
<location filename="../helper.py" line="360"/>
|
||||||
<source>Could not establish a SSH connection to server:
|
<source>Could not establish a SSH connection to server:
|
||||||
|
|
||||||
{0}</source>
|
{0}</source>
|
||||||
@@ -174,7 +174,7 @@ Bitte erneut versuchen.</translation>
|
|||||||
{0}</translation>
|
{0}</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../helper.py" line="376"/>
|
<location filename="../helper.py" line="383"/>
|
||||||
<source>Can not connect to RevPi XML-RPC Service!
|
<source>Can not connect to RevPi XML-RPC Service!
|
||||||
|
|
||||||
This could have the following reasons: The RevPi is not online, the XML-RPC service is not running / bind to localhost or the ACL permission is not set for your IP!!!
|
This could have the following reasons: The RevPi is not online, the XML-RPC service is not running / bind to localhost or the ACL permission is not set for your IP!!!
|
||||||
@@ -401,7 +401,7 @@ Dies kann aus der Textbox oben kopiert werden.</translation>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="231"/>
|
<location filename="../revpicommander.py" line="231"/>
|
||||||
<source>Can not start the simulator! Maybe the piCtory file is corrupt or you have no write permissions for '{0}'.</source>
|
<source>Can not start the simulator! Maybe the piCtory file is corrupt or you have no write permissions for '{0}'.</source>
|
||||||
<translation>Kann Simulator nicht starten! Vielleicht ist die piCtory Datei defekt oder es gibt keine Schreibberechtigung für '{0}`.</translation>
|
<translation>Kann Simulator nicht starten! Vielleicht ist die piCtory Datei defekt oder es gibt keine Schreibberechtigung für '{0}'.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../revpicommander.py" line="398"/>
|
<location filename="../revpicommander.py" line="398"/>
|
||||||
@@ -952,6 +952,27 @@ Dies ist kein Fehler, wenn das SPS Startprogramm bereits auf dem Rev Pi ist. Pr
|
|||||||
{0}.</translation>
|
{0}.</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>SSHAuth</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../sshauth.py" line="49"/>
|
||||||
|
<source>Could not save password</source>
|
||||||
|
<translation>Konnte Kennwort nicht speichern</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../sshauth.py" line="49"/>
|
||||||
|
<source>Could not save password to operating systems password save.
|
||||||
|
|
||||||
|
Maybe your operating system does not support saving passwords. This could be due to missing libraries or programs.
|
||||||
|
|
||||||
|
This is not an error of RevPi Commander.</source>
|
||||||
|
<translation>Konnte das Kennwort nicht im Kennwortspeicher des Betriebssystems speichern.
|
||||||
|
|
||||||
|
Vielleicht untersützt das Betriebssystem keine Kennwortspeicherung. Dies könnte an fehlenden Bibliotheken oder Programmen liegen.
|
||||||
|
|
||||||
|
Dies ist kein Fehler von RevPi Commander.</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Simulator</name>
|
<name>Simulator</name>
|
||||||
<message>
|
<message>
|
||||||
@@ -1672,6 +1693,16 @@ applicable law.
|
|||||||
<source>SSH password:</source>
|
<source>SSH password:</source>
|
||||||
<translation>SSH Passwort:</translation>
|
<translation>SSH Passwort:</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../../../ui_dev/sshauth.ui" line="53"/>
|
||||||
|
<source>Username and password will be saved in secured operating systems's password storage.</source>
|
||||||
|
<translation>Benutzername und Kennwort werden im Passwortspeicher vom Betriebssystem gesichert.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../../../ui_dev/sshauth.ui" line="56"/>
|
||||||
|
<source>Save username and password</source>
|
||||||
|
<translation>Benutzername und Kennwort merken</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>wid_debugcontrol</name>
|
<name>wid_debugcontrol</name>
|
||||||
|
|||||||
BIN
src/revpicommander/locale/revpicommander_en.qm
Normal file
BIN
src/revpicommander/locale/revpicommander_en.qm
Normal file
Binary file not shown.
@@ -4,36 +4,88 @@ __author__ = "Sven Sager"
|
|||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "GPLv3"
|
__license__ = "GPLv3"
|
||||||
|
|
||||||
from enum import Enum
|
from logging import getLogger
|
||||||
|
|
||||||
|
import keyring
|
||||||
from PyQt5 import QtWidgets
|
from PyQt5 import QtWidgets
|
||||||
|
from keyring.errors import KeyringError
|
||||||
|
|
||||||
from revpicommander.ui.sshauth_ui import Ui_diag_sshauth
|
from .ui.sshauth_ui import Ui_diag_sshauth
|
||||||
|
|
||||||
|
log = getLogger()
|
||||||
class SSHAuthType(Enum):
|
|
||||||
PASS = "pass"
|
|
||||||
KEYS = "keys"
|
|
||||||
|
|
||||||
|
|
||||||
class SSHAuth(QtWidgets.QDialog, Ui_diag_sshauth):
|
class SSHAuth(QtWidgets.QDialog, Ui_diag_sshauth):
|
||||||
"""Version information window."""
|
|
||||||
|
|
||||||
def __init__(self, auth_type: SSHAuthType, parent=None):
|
def __init__(self, user_name="", service_name: str = None, parent=None):
|
||||||
|
"""
|
||||||
|
Ask the user for username and password or use saved entries.
|
||||||
|
|
||||||
|
If you want to use the operating system's password storage, you have
|
||||||
|
to set a 'service_name'. The value must be unique for your application
|
||||||
|
or for each user, if the username is the same.
|
||||||
|
|
||||||
|
:param user_name: Preset username, also used to check password save
|
||||||
|
:param service_name: Identity to save passwords in os's password save
|
||||||
|
:param parent: Qt parent for this dialog
|
||||||
|
"""
|
||||||
|
log.debug("SSHAuth.__init__")
|
||||||
|
|
||||||
super(SSHAuth, self).__init__(parent)
|
super(SSHAuth, self).__init__(parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.wid_password.setVisible(auth_type is SSHAuthType.PASS)
|
self._service_name = service_name
|
||||||
self.wid_keys.setVisible(auth_type is SSHAuthType.KEYS)
|
self.cbx_save_password.setVisible(bool(service_name))
|
||||||
|
self.txt_username.setText(user_name)
|
||||||
|
|
||||||
|
def accept(self) -> None:
|
||||||
|
log.debug("SSHAuth.accept")
|
||||||
|
|
||||||
|
if self._service_name and self.cbx_save_password.isChecked():
|
||||||
|
try:
|
||||||
|
keyring.set_password(self._service_name, self.username, self.password)
|
||||||
|
except KeyringError as e:
|
||||||
|
log.error(e)
|
||||||
|
QtWidgets.QMessageBox.warning(
|
||||||
|
self, self.tr("Could not save password"), self.tr(
|
||||||
|
"Could not save password to operating systems password save.\n\n"
|
||||||
|
"Maybe your operating system does not support saving passwords. "
|
||||||
|
"This could be due to missing libraries or programs.\n\n"
|
||||||
|
"This is not an error of RevPi Commander."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
super().accept()
|
||||||
|
|
||||||
|
def exec(self) -> int:
|
||||||
|
log.debug("SSHAuth.exec")
|
||||||
|
|
||||||
|
if self._service_name:
|
||||||
|
try:
|
||||||
|
saved_password = keyring.get_password(self._service_name, self.username)
|
||||||
|
if saved_password:
|
||||||
|
self.txt_password.setText(saved_password)
|
||||||
|
return QtWidgets.QDialog.Accepted
|
||||||
|
except KeyringError as e:
|
||||||
|
log.error(e)
|
||||||
|
|
||||||
|
return super().exec()
|
||||||
|
|
||||||
|
def remove_saved_password(self) -> None:
|
||||||
|
"""Remove saved password."""
|
||||||
|
log.debug("SSHAuth.remove_saved_password")
|
||||||
|
|
||||||
|
if self._service_name:
|
||||||
|
try:
|
||||||
|
keyring.delete_password(self._service_name, self.username)
|
||||||
|
except KeyringError as e:
|
||||||
|
log.error(e)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def password(self) -> str:
|
def password(self) -> str:
|
||||||
|
"""Get the saved or entered password."""
|
||||||
return self.txt_password.text()
|
return self.txt_password.text()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def username(self) -> str:
|
def username(self) -> str:
|
||||||
|
"""Get the entered username."""
|
||||||
return self.txt_username.text()
|
return self.txt_username.text()
|
||||||
|
|
||||||
@username.setter
|
|
||||||
def username(self, value: str):
|
|
||||||
self.txt_username.setText(value)
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class Ui_diag_sshauth(object):
|
|||||||
def setupUi(self, diag_sshauth):
|
def setupUi(self, diag_sshauth):
|
||||||
diag_sshauth.setObjectName("diag_sshauth")
|
diag_sshauth.setObjectName("diag_sshauth")
|
||||||
diag_sshauth.setWindowModality(QtCore.Qt.ApplicationModal)
|
diag_sshauth.setWindowModality(QtCore.Qt.ApplicationModal)
|
||||||
diag_sshauth.resize(275, 170)
|
diag_sshauth.resize(363, 163)
|
||||||
self.verticalLayout = QtWidgets.QVBoxLayout(diag_sshauth)
|
self.verticalLayout = QtWidgets.QVBoxLayout(diag_sshauth)
|
||||||
self.verticalLayout.setObjectName("verticalLayout")
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
self.wid_password = QtWidgets.QWidget(diag_sshauth)
|
self.wid_password = QtWidgets.QWidget(diag_sshauth)
|
||||||
@@ -36,18 +36,18 @@ class Ui_diag_sshauth(object):
|
|||||||
self.txt_username.setObjectName("txt_username")
|
self.txt_username.setObjectName("txt_username")
|
||||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.txt_username)
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.txt_username)
|
||||||
self.verticalLayout.addWidget(self.wid_password)
|
self.verticalLayout.addWidget(self.wid_password)
|
||||||
self.wid_keys = QtWidgets.QWidget(diag_sshauth)
|
self.cbx_save_password = QtWidgets.QCheckBox(diag_sshauth)
|
||||||
self.wid_keys.setObjectName("wid_keys")
|
self.cbx_save_password.setObjectName("cbx_save_password")
|
||||||
self.verticalLayout.addWidget(self.wid_keys)
|
self.verticalLayout.addWidget(self.cbx_save_password)
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox(diag_sshauth)
|
self.btn_box = QtWidgets.QDialogButtonBox(diag_sshauth)
|
||||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
self.btn_box.setOrientation(QtCore.Qt.Horizontal)
|
||||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
self.btn_box.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||||
self.buttonBox.setObjectName("buttonBox")
|
self.btn_box.setObjectName("btn_box")
|
||||||
self.verticalLayout.addWidget(self.buttonBox)
|
self.verticalLayout.addWidget(self.btn_box)
|
||||||
|
|
||||||
self.retranslateUi(diag_sshauth)
|
self.retranslateUi(diag_sshauth)
|
||||||
self.buttonBox.accepted.connect(diag_sshauth.accept) # type: ignore
|
self.btn_box.accepted.connect(diag_sshauth.accept) # type: ignore
|
||||||
self.buttonBox.rejected.connect(diag_sshauth.reject) # type: ignore
|
self.btn_box.rejected.connect(diag_sshauth.reject) # type: ignore
|
||||||
QtCore.QMetaObject.connectSlotsByName(diag_sshauth)
|
QtCore.QMetaObject.connectSlotsByName(diag_sshauth)
|
||||||
|
|
||||||
def retranslateUi(self, diag_sshauth):
|
def retranslateUi(self, diag_sshauth):
|
||||||
@@ -55,6 +55,8 @@ class Ui_diag_sshauth(object):
|
|||||||
diag_sshauth.setWindowTitle(_translate("diag_sshauth", "SSH authentication"))
|
diag_sshauth.setWindowTitle(_translate("diag_sshauth", "SSH authentication"))
|
||||||
self.lbl_username.setText(_translate("diag_sshauth", "SSH username:"))
|
self.lbl_username.setText(_translate("diag_sshauth", "SSH username:"))
|
||||||
self.lbl_password.setText(_translate("diag_sshauth", "SSH password:"))
|
self.lbl_password.setText(_translate("diag_sshauth", "SSH password:"))
|
||||||
|
self.cbx_save_password.setToolTip(_translate("diag_sshauth", "Username and password will be saved in secured operating systems\'s password storage."))
|
||||||
|
self.cbx_save_password.setText(_translate("diag_sshauth", "Save username and password"))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
[DEFAULT]
|
|
||||||
Debian-Version=1
|
|
||||||
Depends3=python3-pyqt5, python3-revpimodio2 (>= 2.5.0), python3-zeroconf (>= 0.24.4)
|
|
||||||
Section=universe/x11
|
|
||||||
Suite=stable
|
|
||||||
X-Python3-Version: >=3.4
|
|
||||||
@@ -11,6 +11,7 @@ SOURCES = src/revpicommander/aclmanager.py \
|
|||||||
src/revpicommander/revpiplclist.py \
|
src/revpicommander/revpiplclist.py \
|
||||||
src/revpicommander/revpiprogram.py \
|
src/revpicommander/revpiprogram.py \
|
||||||
src/revpicommander/simulator.py \
|
src/revpicommander/simulator.py \
|
||||||
|
src/revpicommander/sshauth.py \
|
||||||
src/revpicommander/revpicommander.py
|
src/revpicommander/revpicommander.py
|
||||||
|
|
||||||
FORMS = ui_dev/aclmanager.ui \
|
FORMS = ui_dev/aclmanager.ui \
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>275</width>
|
<width>363</width>
|
||||||
<height>170</height>
|
<height>163</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -48,10 +48,17 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="wid_keys" native="true"/>
|
<widget class="QCheckBox" name="cbx_save_password">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Username and password will be saved in secured operating systems's password storage.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Save username and password</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QDialogButtonBox" name="btn_box">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
@@ -65,7 +72,7 @@
|
|||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>buttonBox</sender>
|
<sender>btn_box</sender>
|
||||||
<signal>accepted()</signal>
|
<signal>accepted()</signal>
|
||||||
<receiver>diag_sshauth</receiver>
|
<receiver>diag_sshauth</receiver>
|
||||||
<slot>accept()</slot>
|
<slot>accept()</slot>
|
||||||
@@ -81,7 +88,7 @@
|
|||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>buttonBox</sender>
|
<sender>btn_box</sender>
|
||||||
<signal>rejected()</signal>
|
<signal>rejected()</signal>
|
||||||
<receiver>diag_sshauth</receiver>
|
<receiver>diag_sshauth</receiver>
|
||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
|
|||||||
Reference in New Issue
Block a user