src/eric7/WebBrowser/WebAuth/Fido2PinDialog.py

branch
eric7
changeset 10854
30c45bd597e6
child 10856
b19cefceca15
equal deleted inserted replaced
10853:1f651b204780 10854:30c45bd597e6
1 # -*- coding: utf-8 -*-
2 # Copyright (c) 2024 Detlev Offenbach <detlev@die-offenbachs.de>
3 #
4
5 """
6 Module implementing a dialog to enter the current and potentially new PIN.
7 """
8
9 import enum
10
11 from PyQt6.QtCore import pyqtSlot
12 from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QLineEdit
13
14 from eric7.EricGui import EricPixmapCache
15
16 from .Ui_Fido2PinDialog import Ui_Fido2PinDialog
17
18
19 class Fido2PinDialogMode(enum.Enum):
20 """
21 Class defining the various PIN dialog mode.
22 """
23
24 GET = 0
25 SET = 1
26 CHANGE = 2
27
28
29 class Fido2PinDialog(QDialog, Ui_Fido2PinDialog):
30 """
31 Class implementing a dialog to enter the current and potentially new PIN.
32 """
33
34 def __init__(self, mode, title, message, minLength, parent=None):
35 """
36 Constructor
37
38 @param mode mode of the dialog
39 @type Fido2PinDialogMode
40 @param title header title to be shown
41 @type str
42 @param message more decriptive text to be shown
43 @type str
44 @param minLength minimum PIN length
45 @type int
46 @param parent reference to the parent widget (defaults to None)
47 @type QWidget (optional)
48 """
49 super().__init__(parent)
50 self.setupUi(self)
51
52 self.pinButton.setIcon(EricPixmapCache.getIcon("showPassword"))
53 self.newPinButton.setIcon(EricPixmapCache.getIcon("showPassword"))
54
55 self.__minLength = minLength
56 self.__mode = mode
57
58 if title:
59 self.headerLabel.setText(f"<b>{title}</b>")
60 else:
61 self.headerLabel.setVisible(False)
62 if message:
63 self.descriptionLabel.setText(message)
64 else:
65 self.descriptionLabel.setVisible(False)
66 self.pinErrorLabel.setVisible(False)
67
68 if mode == Fido2PinDialogMode.GET:
69 self.newPinGroupBox.setVisible(False)
70 elif mode == Fido2PinDialogMode.SET:
71 self.pinLabel.setVisible(False)
72 self.pinEdit.setVisible(False)
73 self.pinButton.setVisible(False)
74 elif mode == Fido2PinDialogMode.CHANGE:
75 # all entries visible
76 pass
77
78 self.pinEdit.textEdited.connect(self.__checkPins)
79 self.newPinEdit.textEdited.connect(self.__checkPins)
80 self.confirmNewPinEdit.textEdited.connect(self.__checkPins)
81
82 self.__checkPins()
83
84 @pyqtSlot()
85 def __checkPins(self):
86 """
87 Private slot to check the entered PIN(s).
88
89 Appropriate error messages are shown in case of issues and the state of
90 the OK button is set accordingly.
91 """
92 messages = []
93
94 if (
95 self.__mode in (Fido2PinDialogMode.GET, Fido2PinDialogMode.CHANGE)
96 and not self.pinEdit.text()
97 ):
98 messages.append(self.tr("PIN must not be empty."))
99 if self.__mode in (Fido2PinDialogMode.SET, Fido2PinDialogMode.CHANGE):
100 if len(self.newPinEdit.text()) < self.__minLength:
101 messages.append(
102 self.tr("New PIN is TOO short (minimum length: {0}).").format(
103 self.__minLength
104 )
105 )
106 if (
107 self.confirmNewPinEdit.isVisible()
108 and self.confirmNewPinEdit.text() != self.newPinEdit.text()
109 ):
110 messages.append("New PIN confirmation does not match.")
111 if (
112 self.__mode == Fido2PinDialogMode.CHANGE
113 and self.pinEdit.text() == self.newPinEdit.text()
114 ):
115 messages.append(self.tr("Old and new PIN must not be identical."))
116
117 self.__showPinErrors(messages)
118 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(
119 not bool(messages)
120 )
121
122 def __showPinErrors(self, errorMessages):
123 """
124 Private method to show some error messages.
125
126 @param errorMessages list of error messages
127 @type list of str
128 """
129 if not errorMessages:
130 self.pinErrorLabel.clear()
131 self.pinErrorLabel.setVisible(False)
132 else:
133 if len(errorMessages) == 1:
134 msg = errorMessages[0]
135 else:
136 msg = "<ul><li>{0}</li></ul>".format("</li><li>".join(errorMessages))
137 self.pinErrorLabel.setText(msg)
138 self.pinErrorLabel.setVisible(True)
139
140 self.adjustSize()
141
142 @pyqtSlot(bool)
143 def on_pinButton_toggled(self, checked):
144 """
145 Private slot to handle the toggling of the PIN visibility.
146
147 @param checked state of the PIN visibility button
148 @type bool
149 """
150 if checked:
151 self.pinButton.setIcon(EricPixmapCache.getIcon("hidePassword"))
152 self.pinEdit.setEchoMode(QLineEdit.EchoMode.Normal)
153 else:
154 self.pinButton.setIcon(EricPixmapCache.getIcon("showPassword"))
155 self.pinEdit.setEchoMode(QLineEdit.EchoMode.Password)
156
157 @pyqtSlot(bool)
158 def on_newPinButton_toggled(self, checked):
159 """
160 Private slot to handle the toggling of the new PIN visibility.
161
162 @param checked state of the new PIN visibility button
163 @type bool
164 """
165 if checked:
166 self.newPinButton.setIcon(EricPixmapCache.getIcon("hidePassword"))
167 self.newPinEdit.setEchoMode(QLineEdit.EchoMode.Normal)
168 else:
169 self.newPinButton.setIcon(EricPixmapCache.getIcon("showPassword"))
170 self.newPinEdit.setEchoMode(QLineEdit.EchoMode.Password)
171
172 self.confirmnewPinLabel.setVisible(not checked)
173 self.confirmPinnewEdit.setVisible(not checked)
174 self.on_newPinEdit_textEdited(self.newPinEdit.text())
175
176 def getPins(self):
177 """
178 Public method to get the entered PINs.
179
180 @return tuple containing the current and new PIN
181 @rtype tuple of (str, str)
182 """
183 if self.__mode == Fido2PinDialogMode.GET:
184 return self.pinEdit.text(), None
185 elif self.__mode == Fido2PinDialogMode.SET:
186 return None, self.newPinEdit.text()
187 elif self.__mode == Fido2PinDialogMode.GET:
188 return self.pinEdit.text(), self.newPinEdit.text()
189 else:
190 return None, None

eric ide

mercurial