mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-12-23 10:11:52 +03:00
Merge PR #1450
This commit is contained in:
commit
3a12c3f9a3
@ -42,6 +42,7 @@ from yubikit.logging import LOG_LEVEL
|
||||
from ykman.pcsc import list_devices, YK_READER_NAME
|
||||
from smartcard.Exceptions import SmartcardException, NoCardException
|
||||
from smartcard.pcsc.PCSCExceptions import EstablishContextException
|
||||
from smartcard.CardMonitoring import CardObserver, CardMonitor
|
||||
from hashlib import sha256
|
||||
from dataclasses import asdict
|
||||
from typing import Mapping, Tuple
|
||||
@ -263,9 +264,6 @@ class AbstractDeviceNode(RpcNode):
|
||||
|
||||
|
||||
class UsbDeviceNode(AbstractDeviceNode):
|
||||
def __init__(self, device, info):
|
||||
super().__init__(device, info)
|
||||
|
||||
def _supports_connection(self, conn_type):
|
||||
return self._device.pid.supports_connection(conn_type)
|
||||
|
||||
@ -308,15 +306,53 @@ class UsbDeviceNode(AbstractDeviceNode):
|
||||
raise ConnectionException("fido", e)
|
||||
|
||||
|
||||
class _ReaderObserver(CardObserver):
|
||||
def __init__(self, device):
|
||||
self.device = device
|
||||
self.card = None
|
||||
self.data = None
|
||||
|
||||
def update(self, observable, actions):
|
||||
added, removed = actions
|
||||
for card in added:
|
||||
if card.reader == self.device.reader.name:
|
||||
if card != self.card:
|
||||
self.card = card
|
||||
break
|
||||
else:
|
||||
self.card = None
|
||||
self.data = None
|
||||
logger.debug(f"NFC card: {self.card}")
|
||||
|
||||
|
||||
class ReaderDeviceNode(AbstractDeviceNode):
|
||||
def __init__(self, device, info):
|
||||
super().__init__(device, info)
|
||||
self._observer = _ReaderObserver(device)
|
||||
self._monitor = CardMonitor()
|
||||
self._monitor.addObserver(self._observer)
|
||||
|
||||
def close(self):
|
||||
self._monitor.deleteObserver(self._observer)
|
||||
super().close()
|
||||
|
||||
def get_data(self):
|
||||
try:
|
||||
with self._device.open_connection(SmartCardConnection) as conn:
|
||||
return dict(self._read_data(conn), present=True)
|
||||
except NoCardException:
|
||||
return dict(present=False, status="no-card")
|
||||
except ValueError:
|
||||
return dict(present=False, status="unknown-device")
|
||||
if self._observer.data is None:
|
||||
card = self._observer.card
|
||||
if card is None:
|
||||
return dict(present=False, status="no-card")
|
||||
try:
|
||||
with self._device.open_connection(SmartCardConnection) as conn:
|
||||
self._observer.data = dict(self._read_data(conn), present=True)
|
||||
except NoCardException:
|
||||
return dict(present=False, status="no-card")
|
||||
except ValueError:
|
||||
self._observer.data = dict(present=False, status="unknown-device")
|
||||
return self._observer.data
|
||||
|
||||
@action(closes_child=False)
|
||||
def get(self, params, event, signal):
|
||||
return super().get(params, event, signal)
|
||||
|
||||
@child
|
||||
def ccid(self):
|
||||
|
@ -31,9 +31,8 @@ import 'state.dart';
|
||||
|
||||
const _usbPollDelay = Duration(milliseconds: 500);
|
||||
|
||||
const _nfcPollDelay = Duration(milliseconds: 2500);
|
||||
const _nfcAttachPollDelay = Duration(seconds: 1);
|
||||
const _nfcDetachPollDelay = Duration(seconds: 5);
|
||||
const _nfcPollReadersDelay = Duration(milliseconds: 2500);
|
||||
const _nfcPollCardDelay = Duration(seconds: 1);
|
||||
|
||||
final _log = Logger('desktop.devices');
|
||||
|
||||
@ -197,7 +196,7 @@ class NfcDeviceNotifier extends StateNotifier<List<NfcReaderNode>> {
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
_pollTimer = Timer(_nfcPollDelay, _pollReaders);
|
||||
_pollTimer = Timer(_nfcPollReadersDelay, _pollReaders);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -260,7 +259,7 @@ class CurrentDeviceDataNotifier extends StateNotifier<AsyncValue<YubiKeyData>> {
|
||||
|
||||
void _notifyWindowState(WindowState windowState) {
|
||||
if (windowState.active) {
|
||||
_pollReader();
|
||||
_pollCard();
|
||||
} else {
|
||||
_pollTimer?.cancel();
|
||||
// TODO: Should we clear the key here?
|
||||
@ -276,16 +275,23 @@ class CurrentDeviceDataNotifier extends StateNotifier<AsyncValue<YubiKeyData>> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _pollReader() async {
|
||||
void _pollCard() async {
|
||||
_pollTimer?.cancel();
|
||||
final node = _deviceNode!;
|
||||
try {
|
||||
_log.debug('Polling for USB device changes...');
|
||||
_log.debug('Polling for NFC device changes...');
|
||||
var result = await _rpc?.command('get', node.path.segments);
|
||||
if (mounted && result != null) {
|
||||
if (result['data']['present']) {
|
||||
state = AsyncValue.data(YubiKeyData(node, result['data']['name'],
|
||||
DeviceInfo.fromJson(result['data']['info'])));
|
||||
final oldState = state.valueOrNull;
|
||||
final newState = YubiKeyData(node, result['data']['name'],
|
||||
DeviceInfo.fromJson(result['data']['info']));
|
||||
if (oldState != null && oldState != newState) {
|
||||
// Ensure state is cleared
|
||||
state = const AsyncValue.loading();
|
||||
} else {
|
||||
state = AsyncValue.data(newState);
|
||||
}
|
||||
} else {
|
||||
final status = result['data']['status'];
|
||||
// Only update if status is not changed
|
||||
@ -298,9 +304,7 @@ class CurrentDeviceDataNotifier extends StateNotifier<AsyncValue<YubiKeyData>> {
|
||||
_log.error('Error polling NFC', jsonEncode(e));
|
||||
}
|
||||
if (mounted) {
|
||||
_pollTimer = Timer(
|
||||
state is AsyncData ? _nfcDetachPollDelay : _nfcAttachPollDelay,
|
||||
_pollReader);
|
||||
_pollTimer = Timer(_nfcPollCardDelay, _pollCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ class DesktopCredentialListNotifier extends OathCredentialListNotifier {
|
||||
code = OathCode.fromJson(result);
|
||||
}
|
||||
_log.debug('Calculate', jsonEncode(code));
|
||||
if (update && mounted) {
|
||||
if (update && mounted && state != null) {
|
||||
final creds = state!.toList();
|
||||
final i = creds.indexWhere((e) => e.credential.id == credential.id);
|
||||
state = creds..[i] = creds[i].copyWith(code: code);
|
||||
|
Loading…
Reference in New Issue
Block a user