84 self.__mgmtMenu.addAction(self.tr("Show Info"), self.__showSecurityKeyInfo) |
87 self.__mgmtMenu.addAction(self.tr("Show Info"), self.__showSecurityKeyInfo) |
85 self.__mgmtMenu.addSeparator() |
88 self.__mgmtMenu.addSeparator() |
86 self.__mgmtMenu.addAction( |
89 self.__mgmtMenu.addAction( |
87 self.tr("Reset Security Key"), self.__resetSecurityKey |
90 self.tr("Reset Security Key"), self.__resetSecurityKey |
88 ) |
91 ) |
89 # TODO: potentially add these 'config' actions |
92 self.__mgmtMenu.addSeparator() |
90 # - Force PIN Change |
93 self.__forcePinChangeAct = self.__mgmtMenu.addAction( |
91 # - Set Minimum PIN Length |
94 self.tr("Force PIN Change"), self.__forcePinChange |
92 # - Toggle 'Always Require UV' |
95 ) |
|
96 self.__minPinLengthAct = self.__mgmtMenu.addAction( |
|
97 self.tr("Set Minimum PIN Length"), self.__setMinimumPinLength |
|
98 ) |
|
99 self.__toggleAlwaysUvAct = self.__mgmtMenu.addAction( |
|
100 self.tr("Toggle 'Always Require User Verification'"), self.__toggleAlwaysUv |
|
101 ) |
93 |
102 |
94 self.__mgmtMenu.aboutToShow.connect(self.__aboutToShowManagementMenu) |
103 self.__mgmtMenu.aboutToShow.connect(self.__aboutToShowManagementMenu) |
95 |
104 |
96 self.menuButton.setMenu(self.__mgmtMenu) |
105 self.menuButton.setMenu(self.__mgmtMenu) |
97 |
106 |
98 @pyqtSlot() |
107 @pyqtSlot() |
99 def __aboutToShowManagementMenu(self): |
108 def __aboutToShowManagementMenu(self): |
100 """ |
109 """ |
101 Private slot to prepare the security key management menu before it is shown. |
110 Private slot to prepare the security key management menu before it is shown. |
102 """ |
111 """ |
103 # TODO: not implemented yet |
112 self.__forcePinChangeAct.setEnabled( |
104 pass |
113 self.__manager.forcePinChangeSupported() |
|
114 and not self.__manager.pinChangeRequired() |
|
115 ) |
|
116 self.__minPinLengthAct.setEnabled( |
|
117 self.__manager.canSetMinimumPinLength() |
|
118 and not self.__manager.pinChangeRequired() |
|
119 ) |
|
120 self.__toggleAlwaysUvAct.setEnabled( |
|
121 self.__manager.canToggleAlwaysUv() |
|
122 and not self.__manager.pinChangeRequired() |
|
123 ) |
105 |
124 |
106 ############################################################################ |
125 ############################################################################ |
107 ## methods related to device handling |
126 ## methods related to device handling |
108 ############################################################################ |
127 ############################################################################ |
109 |
128 |
146 Private slot handling the selection of security key. |
162 Private slot handling the selection of security key. |
147 |
163 |
148 @param index index of the selected security key |
164 @param index index of the selected security key |
149 @type int |
165 @type int |
150 """ |
166 """ |
151 self.lockButton.setChecked(False) |
|
152 self.__manager.disconnectFromDevice() |
167 self.__manager.disconnectFromDevice() |
153 |
168 |
154 securityKey = self.securityKeysComboBox.itemData(index) |
169 securityKey = self.securityKeysComboBox.itemData(index) |
155 |
|
156 self.lockButton.setEnabled(securityKey is not None) |
|
157 self.pinButton.setEnabled(securityKey is not None) |
|
158 self.menuButton.setEnabled(securityKey is not None) |
|
159 self.loadPasskeysButton.setEnabled(securityKey is not None) |
|
160 |
|
161 if securityKey is not None: |
170 if securityKey is not None: |
162 self.__manager.connectToDevice(securityKey) |
171 self.__manager.connectToDevice(securityKey) |
163 hasPin = self.__manager.hasPin() |
172 |
164 forcedPinChange = self.__manager.forcedPinChange() |
173 @pyqtSlot() |
165 if hasPin is True: |
174 def __deviceConnected(self): |
166 self.pinButton.setText(self.tr("Change PIN")) |
175 """ |
167 elif hasPin is False: |
176 Private slot handling the device connected signal. |
168 self.pinButton.setText(self.tr("Set PIN")) |
177 """ |
169 else: |
178 self.lockButton.setEnabled(True) |
170 self.pinButton.setEnabled(False) |
179 self.pinButton.setEnabled(True) |
171 if forcedPinChange or hasPin is False: |
180 self.menuButton.setEnabled(True) |
172 self.lockButton.setEnabled(False) |
181 self.loadPasskeysButton.setEnabled(True) |
173 self.loadPasskeysButton.setEnabled(False) |
182 |
174 msg = ( |
183 hasPin = self.__manager.hasPin() |
175 self.tr("A PIN change is required.") |
184 forcedPinChange = self.__manager.pinChangeRequired() |
176 if forcedPinChange |
185 if hasPin is True: |
177 else self.tr("You must set a PIN first.") |
186 self.pinButton.setText(self.tr("Change PIN")) |
178 ) |
187 elif hasPin is False: |
179 EricMessageBox.information( |
188 self.pinButton.setText(self.tr("Set PIN")) |
180 self, |
189 else: |
181 self.tr("FIDO2 Security Key Management"), |
190 self.pinButton.setEnabled(False) |
182 msg, |
191 if forcedPinChange or hasPin is False: |
183 ) |
192 self.lockButton.setEnabled(False) |
|
193 self.loadPasskeysButton.setEnabled(False) |
|
194 msg = ( |
|
195 self.tr("A PIN change is required.") |
|
196 if forcedPinChange |
|
197 else self.tr("You must set a PIN first.") |
|
198 ) |
|
199 EricMessageBox.information( |
|
200 self, |
|
201 self.tr("FIDO2 Security Key Management"), |
|
202 msg, |
|
203 ) |
|
204 |
|
205 self.passkeysList.clear() |
|
206 self.on_passkeysList_itemSelectionChanged() |
|
207 |
|
208 @pyqtSlot() |
|
209 def __deviceDisconnected(self): |
|
210 """ |
|
211 Private slot handling the device disconnected signal. |
|
212 """ |
|
213 self.lockButton.setChecked(False) |
|
214 self.passkeysList.clear() |
|
215 self.on_passkeysList_itemSelectionChanged() |
|
216 |
|
217 self.lockButton.setEnabled(False) |
|
218 self.pinButton.setEnabled(False) |
|
219 self.menuButton.setEnabled(False) |
|
220 self.loadPasskeysButton.setEnabled(False) |
184 |
221 |
185 self.passkeysList.clear() |
222 self.passkeysList.clear() |
186 self.on_passkeysList_itemSelectionChanged() |
223 self.on_passkeysList_itemSelectionChanged() |
187 |
224 |
188 @pyqtSlot(bool) |
225 @pyqtSlot(bool) |
294 msg = self.tr("{0} is not supported by the selected security key.").format( |
331 msg = self.tr("{0} is not supported by the selected security key.").format( |
295 feature |
332 feature |
296 ) |
333 ) |
297 elif not hasPin: |
334 elif not hasPin: |
298 msg = self.tr("{0} requires having a PIN. Set a PIN first.").format(feature) |
335 msg = self.tr("{0} requires having a PIN. Set a PIN first.").format(feature) |
299 elif self.__manager.forcedPinChange(): |
336 elif self.__manager.pinChangeRequired(): |
300 msg = self.tr("The security key is locked. Change the PIN first.") |
337 msg = self.tr("The security key is locked. Change the PIN first.") |
301 elif powerCycle: |
338 elif powerCycle: |
302 msg = self.tr( |
339 msg = self.tr( |
303 "The security key is locked because the wrong PIN was entered " |
340 "The security key is locked because the wrong PIN was entered " |
304 "too many times. To unlock it, remove and reinsert it." |
341 "too many times. To unlock it, remove and reinsert it." |
370 ) |
407 ) |
371 if dlg.exec() == QDialog.DialogCode.Accepted: |
408 if dlg.exec() == QDialog.DialogCode.Accepted: |
372 newPin = dlg.getPins()[1] |
409 newPin = dlg.getPins()[1] |
373 ok, msg = self.__manager.setPin(newPin) |
410 ok, msg = self.__manager.setPin(newPin) |
374 if ok: |
411 if ok: |
375 self.lockButton.setEnabled(True) |
|
376 self.lockButton.setChecked(False) |
|
377 self.pinButton.setText(self.tr("Change PIN")) |
|
378 self.loadPasskeysButton.setEnabled(True) |
|
379 self.__manager.reconnectToDevice() |
|
380 EricMessageBox.information(self, title, msg) |
412 EricMessageBox.information(self, title, msg) |
381 else: |
413 else: |
382 EricMessageBox.warning(self, title, msg) |
414 EricMessageBox.warning(self, title, msg) |
383 |
415 |
384 @pyqtSlot() |
416 @pyqtSlot() |
399 ) |
431 ) |
400 if dlg.exec() == QDialog.DialogCode.Accepted: |
432 if dlg.exec() == QDialog.DialogCode.Accepted: |
401 oldPin, newPin = dlg.getPins() |
433 oldPin, newPin = dlg.getPins() |
402 ok, msg = self.__manager.changePin(oldPin, newPin) |
434 ok, msg = self.__manager.changePin(oldPin, newPin) |
403 if ok: |
435 if ok: |
404 self.lockButton.setChecked(False) |
|
405 EricMessageBox.information(self, title, msg) |
436 EricMessageBox.information(self, title, msg) |
406 else: |
437 else: |
407 EricMessageBox.warning(self, title, msg) |
438 EricMessageBox.warning(self, title, msg) |
408 |
439 |
409 @pyqtSlot() |
440 @pyqtSlot() |
579 index = self.passkeysList.indexOfTopLevelItem(rpItem) |
610 index = self.passkeysList.indexOfTopLevelItem(rpItem) |
580 self.passkeysList.takeTopLevelItem(index) |
611 self.passkeysList.takeTopLevelItem(index) |
581 del rpItem |
612 del rpItem |
582 |
613 |
583 ############################################################################ |
614 ############################################################################ |
|
615 ## methods related to device configuration |
|
616 ############################################################################ |
|
617 |
|
618 @pyqtSlot() |
|
619 def __forcePinChange(self): |
|
620 """ |
|
621 Private slot to force a PIN change before the next use. |
|
622 """ |
|
623 pin = self.__getRequiredPin(feature=self.tr("Force PIN Change")) |
|
624 try: |
|
625 self.__manager.forcePinChange(pin=pin) |
|
626 except (Fido2DeviceError, Fido2PinError) as err: |
|
627 self.__handleError( |
|
628 error=err, |
|
629 title=self.tr("Force PIN Change"), |
|
630 message=self.tr("The 'Force PIN Change' flag could not be set."), |
|
631 ) |
|
632 |
|
633 @pyqtSlot() |
|
634 def __setMinimumPinLength(self): |
|
635 """ |
|
636 Private slot to set the minimum PIN length. |
|
637 """ |
|
638 currMinLength = self.__manager.getMinimumPinLength() |
|
639 |
|
640 minPinLength, ok = QInputDialog.getInt( |
|
641 self, |
|
642 self.tr("Set Minimum PIN Length"), |
|
643 self.tr("Enter the minimum PIN length (between {0} and 63):").format( |
|
644 currMinLength |
|
645 ), |
|
646 0, |
|
647 currMinLength, |
|
648 63, |
|
649 1, |
|
650 ) |
|
651 if ok and minPinLength != currMinLength: |
|
652 pin = self.__getRequiredPin(feature=self.tr("Set Minimum PIN Length")) |
|
653 try: |
|
654 self.__manager.setMinimumPinLength(pin=pin, minLength=minPinLength) |
|
655 EricMessageBox.information( |
|
656 self, |
|
657 self.tr("Set Minimum PIN Length"), |
|
658 self.tr("The minimum PIN length was set to be {0}.").format( |
|
659 minPinLength |
|
660 ), |
|
661 ) |
|
662 except (Fido2DeviceError, Fido2PinError) as err: |
|
663 self.__handleError( |
|
664 error=err, |
|
665 title=self.tr("Set Minimum PIN Length"), |
|
666 message=self.tr("The minimum PIN length could not be set."), |
|
667 ) |
|
668 |
|
669 @pyqtSlot() |
|
670 def __toggleAlwaysUv(self): |
|
671 """ |
|
672 Private slot to toggle the state of the 'Always Require User Verification' |
|
673 flag. |
|
674 """ |
|
675 pin = self.__getRequiredPin( |
|
676 feature=self.tr("Toggle 'Always Require User Verification'") |
|
677 ) |
|
678 try: |
|
679 self.__manager.toggleAlwaysUv(pin=pin) |
|
680 EricMessageBox.information( |
|
681 self, |
|
682 self.tr("Always Require User Verification"), |
|
683 self.tr("Always Require User Verification is now enabled.") |
|
684 if self.__manager.getAlwaysUv() |
|
685 else self.tr("Always Require User Verification is now disabled."), |
|
686 ) |
|
687 |
|
688 except (Fido2DeviceError, Fido2PinError) as err: |
|
689 self.__handleError( |
|
690 error=err, |
|
691 title=self.tr("Toggle 'Always Require User Verification'"), |
|
692 message=self.tr( |
|
693 "The 'Always Require User Verification' flag could not be toggled." |
|
694 ), |
|
695 ) |
|
696 |
|
697 ############################################################################ |
584 ## utility methods |
698 ## utility methods |
585 ############################################################################ |
699 ############################################################################ |
586 |
700 |
587 def __handleError(self, error, title, message): |
701 def __handleError(self, error, title, message): |
588 """ |
702 """ |