mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-12-23 18:22:39 +03:00
Merge PR #1472
This commit is contained in:
commit
f674836397
@ -49,8 +49,10 @@ data class Info(
|
|||||||
val isNfc: Boolean,
|
val isNfc: Boolean,
|
||||||
@SerialName("usb_pid")
|
@SerialName("usb_pid")
|
||||||
val usbPid: Int?,
|
val usbPid: Int?,
|
||||||
|
@SerialName("pin_complexity")
|
||||||
|
val pinComplexity: Boolean,
|
||||||
@SerialName("supported_capabilities")
|
@SerialName("supported_capabilities")
|
||||||
val supportedCapabilities: Capabilities
|
val supportedCapabilities: Capabilities,
|
||||||
) {
|
) {
|
||||||
constructor(name: String, isNfc: Boolean, usbPid: Int?, deviceInfo: DeviceInfo) : this(
|
constructor(name: String, isNfc: Boolean, usbPid: Int?, deviceInfo: DeviceInfo) : this(
|
||||||
config = Config(deviceInfo.config),
|
config = Config(deviceInfo.config),
|
||||||
@ -63,6 +65,7 @@ data class Info(
|
|||||||
name = name,
|
name = name,
|
||||||
isNfc = isNfc,
|
isNfc = isNfc,
|
||||||
usbPid = usbPid,
|
usbPid = usbPid,
|
||||||
|
pinComplexity = deviceInfo.pinComplexity,
|
||||||
supportedCapabilities = Capabilities(
|
supportedCapabilities = Capabilities(
|
||||||
nfc = deviceInfo.capabilitiesFor(Transport.NFC),
|
nfc = deviceInfo.capabilitiesFor(Transport.NFC),
|
||||||
usb = deviceInfo.capabilitiesFor(Transport.USB),
|
usb = deviceInfo.capabilitiesFor(Transport.USB),
|
||||||
|
@ -18,5 +18,6 @@ val UnknownDevice = Info(
|
|||||||
name = "Unrecognized device",
|
name = "Unrecognized device",
|
||||||
isNfc = false,
|
isNfc = false,
|
||||||
usbPid = null,
|
usbPid = null,
|
||||||
|
pinComplexity = false,
|
||||||
supportedCapabilities = Capabilities()
|
supportedCapabilities = Capabilities()
|
||||||
)
|
)
|
@ -313,18 +313,28 @@ class FidoManager(
|
|||||||
} catch (ctapException: CtapException) {
|
} catch (ctapException: CtapException) {
|
||||||
if (ctapException.ctapError == CtapException.ERR_PIN_INVALID ||
|
if (ctapException.ctapError == CtapException.ERR_PIN_INVALID ||
|
||||||
ctapException.ctapError == CtapException.ERR_PIN_BLOCKED ||
|
ctapException.ctapError == CtapException.ERR_PIN_BLOCKED ||
|
||||||
ctapException.ctapError == CtapException.ERR_PIN_AUTH_BLOCKED
|
ctapException.ctapError == CtapException.ERR_PIN_AUTH_BLOCKED ||
|
||||||
|
ctapException.ctapError == CtapException.ERR_PIN_POLICY_VIOLATION
|
||||||
) {
|
) {
|
||||||
pinStore.setPin(null)
|
pinStore.setPin(null)
|
||||||
fidoViewModel.updateCredentials(emptyList())
|
fidoViewModel.updateCredentials(emptyList())
|
||||||
val pinRetriesResult = clientPin.pinRetries
|
|
||||||
JSONObject(
|
if (ctapException.ctapError == CtapException.ERR_PIN_POLICY_VIOLATION) {
|
||||||
mapOf(
|
JSONObject(
|
||||||
"success" to false,
|
mapOf(
|
||||||
"pinRetries" to pinRetriesResult.count,
|
"success" to false,
|
||||||
"authBlocked" to (ctapException.ctapError == CtapException.ERR_PIN_AUTH_BLOCKED)
|
"pinViolation" to true
|
||||||
)
|
)
|
||||||
).toString()
|
).toString()
|
||||||
|
} else {
|
||||||
|
JSONObject(
|
||||||
|
mapOf(
|
||||||
|
"success" to false,
|
||||||
|
"pinRetries" to clientPin.pinRetries.count,
|
||||||
|
"authBlocked" to (ctapException.ctapError == CtapException.ERR_PIN_AUTH_BLOCKED),
|
||||||
|
)
|
||||||
|
).toString()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw ctapException
|
throw ctapException
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,7 @@ class SkyHelper(private val compatUtil: CompatUtil) {
|
|||||||
name = (device.usbDevice.productName ?: "Yubico Security Key"),
|
name = (device.usbDevice.productName ?: "Yubico Security Key"),
|
||||||
isNfc = false,
|
isNfc = false,
|
||||||
usbPid = pid.value,
|
usbPid = pid.value,
|
||||||
|
pinComplexity = false,
|
||||||
supportedCapabilities = Capabilities(usb = 0)
|
supportedCapabilities = Capabilities(usb = 0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,11 @@ class AuthRequiredException(RpcException):
|
|||||||
super().__init__("auth-required", "Authentication is required")
|
super().__init__("auth-required", "Authentication is required")
|
||||||
|
|
||||||
|
|
||||||
|
class PinComplexityException(RpcException):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("pin-complexity", "PIN does not meet complexity requirements")
|
||||||
|
|
||||||
|
|
||||||
class ChildResetException(Exception):
|
class ChildResetException(Exception):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
self.message = message
|
self.message = message
|
||||||
|
@ -19,6 +19,7 @@ from .base import (
|
|||||||
RpcException,
|
RpcException,
|
||||||
TimeoutException,
|
TimeoutException,
|
||||||
AuthRequiredException,
|
AuthRequiredException,
|
||||||
|
PinComplexityException,
|
||||||
)
|
)
|
||||||
from fido2.ctap import CtapError
|
from fido2.ctap import CtapError
|
||||||
from fido2.ctap2 import Ctap2, ClientPin
|
from fido2.ctap2 import Ctap2, ClientPin
|
||||||
@ -76,6 +77,8 @@ def _handle_pin_error(e, client_pin):
|
|||||||
raise PinValidationException(
|
raise PinValidationException(
|
||||||
pin_retries, e.code == CtapError.ERR.PIN_AUTH_BLOCKED
|
pin_retries, e.code == CtapError.ERR.PIN_AUTH_BLOCKED
|
||||||
)
|
)
|
||||||
|
if e.code == CtapError.ERR.PIN_POLICY_VIOLATION:
|
||||||
|
raise PinComplexityException()
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ from .base import (
|
|||||||
ChildResetException,
|
ChildResetException,
|
||||||
TimeoutException,
|
TimeoutException,
|
||||||
AuthRequiredException,
|
AuthRequiredException,
|
||||||
|
PinComplexityException,
|
||||||
)
|
)
|
||||||
from yubikit.core import NotSupportedError, BadResponseError, InvalidPinError
|
from yubikit.core import NotSupportedError, BadResponseError, InvalidPinError
|
||||||
from yubikit.core.smartcard import ApduError, SW
|
from yubikit.core.smartcard import ApduError, SW
|
||||||
@ -80,6 +81,15 @@ class GENERATE_TYPE(str, Enum):
|
|||||||
CERTIFICATE = "certificate"
|
CERTIFICATE = "certificate"
|
||||||
|
|
||||||
|
|
||||||
|
def _handle_pin_puk_error(e):
|
||||||
|
if isinstance(e, ApduError):
|
||||||
|
if e.sw == SW.CONDITIONS_NOT_SATISFIED:
|
||||||
|
raise PinComplexityException()
|
||||||
|
if isinstance(e, InvalidPinError):
|
||||||
|
raise InvalidPinException(cause=e)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
class PivNode(RpcNode):
|
class PivNode(RpcNode):
|
||||||
def __init__(self, connection):
|
def __init__(self, connection):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@ -208,21 +218,30 @@ class PivNode(RpcNode):
|
|||||||
def change_pin(self, params, event, signal):
|
def change_pin(self, params, event, signal):
|
||||||
old_pin = params.pop("pin")
|
old_pin = params.pop("pin")
|
||||||
new_pin = params.pop("new_pin")
|
new_pin = params.pop("new_pin")
|
||||||
pivman_change_pin(self.session, old_pin, new_pin)
|
try:
|
||||||
|
pivman_change_pin(self.session, old_pin, new_pin)
|
||||||
|
except Exception as e:
|
||||||
|
_handle_pin_puk_error(e)
|
||||||
return dict()
|
return dict()
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def change_puk(self, params, event, signal):
|
def change_puk(self, params, event, signal):
|
||||||
old_puk = params.pop("puk")
|
old_puk = params.pop("puk")
|
||||||
new_puk = params.pop("new_puk")
|
new_puk = params.pop("new_puk")
|
||||||
self.session.change_puk(old_puk, new_puk)
|
try:
|
||||||
|
self.session.change_puk(old_puk, new_puk)
|
||||||
|
except Exception as e:
|
||||||
|
_handle_pin_puk_error(e)
|
||||||
return dict()
|
return dict()
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def unblock_pin(self, params, event, signal):
|
def unblock_pin(self, params, event, signal):
|
||||||
puk = params.pop("puk")
|
puk = params.pop("puk")
|
||||||
new_pin = params.pop("new_pin")
|
new_pin = params.pop("new_pin")
|
||||||
self.session.unblock_pin(puk, new_pin)
|
try:
|
||||||
|
self.session.unblock_pin(puk, new_pin)
|
||||||
|
except Exception as e:
|
||||||
|
_handle_pin_puk_error(e)
|
||||||
return dict()
|
return dict()
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
12
helper/poetry.lock
generated
12
helper/poetry.lock
generated
@ -1,4 +1,4 @@
|
|||||||
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "altgraph"
|
name = "altgraph"
|
||||||
@ -717,13 +717,13 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yubikey-manager"
|
name = "yubikey-manager"
|
||||||
version = "5.3.0"
|
version = "5.4.0"
|
||||||
description = "Tool for managing your YubiKey configuration."
|
description = "Tool for managing your YubiKey configuration."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8,<4.0"
|
python-versions = "<4.0,>=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "yubikey_manager-5.3.0-py3-none-any.whl", hash = "sha256:9a809620f5c910c1047323570095e10b885002f6b0a2e4d8ced7f62d7c2ce628"},
|
{file = "yubikey_manager-5.4.0-py3-none-any.whl", hash = "sha256:d53acb06c4028a833be7a05ca4145833afef1affa67aaab4347bc50ecce37985"},
|
||||||
{file = "yubikey_manager-5.3.0.tar.gz", hash = "sha256:5492c36a10ce6a5995b8ea1d32cf5bd60db7587201b2aa3e63e0c1da2334b8b6"},
|
{file = "yubikey_manager-5.4.0.tar.gz", hash = "sha256:53726a186722cd2683b2f5fd781fc0a2861f47ce62ba9d3527960832c8fabec8"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -787,4 +787,4 @@ files = [
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.8"
|
python-versions = "^3.8"
|
||||||
content-hash = "6664f12e752d8b41c996d11e43a8572ed47f7fbfaaf84fa894be725fe2208d80"
|
content-hash = "7543cc0ac90ea4eb701a7f52321d831bfe05c65e0ae896a6107eb7a9540d8543"
|
||||||
|
@ -10,7 +10,7 @@ packages = [
|
|||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.8"
|
python = "^3.8"
|
||||||
yubikey-manager = "^5.2"
|
yubikey-manager = "^5.4"
|
||||||
mss = "^9.0.1"
|
mss = "^9.0.1"
|
||||||
Pillow = "^10.2.0"
|
Pillow = "^10.2.0"
|
||||||
zxing-cpp = "^2.2.0"
|
zxing-cpp = "^2.2.0"
|
||||||
|
@ -109,15 +109,18 @@ class _FidoStateNotifier extends FidoStateNotifier {
|
|||||||
},
|
},
|
||||||
));
|
));
|
||||||
if (response['success'] == true) {
|
if (response['success'] == true) {
|
||||||
_log.debug('FIDO pin set/change successful');
|
_log.debug('FIDO PIN set/change successful');
|
||||||
return PinResult.success();
|
return PinResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
_log.debug('FIDO pin set/change failed');
|
if (response['pinViolation'] == true) {
|
||||||
return PinResult.failed(
|
_log.debug('FIDO PIN violation');
|
||||||
response['pinRetries'],
|
return PinResult.failed(const FidoPinFailureReason.weakPin());
|
||||||
response['authBlocked'],
|
}
|
||||||
);
|
|
||||||
|
_log.debug('FIDO PIN set/change failed');
|
||||||
|
return PinResult.failed(FidoPinFailureReason.invalidPin(
|
||||||
|
response['pinRetries'], response['authBlocked']));
|
||||||
} on PlatformException catch (pe) {
|
} on PlatformException catch (pe) {
|
||||||
var decodedException = pe.decode();
|
var decodedException = pe.decode();
|
||||||
if (decodedException is CancellationException) {
|
if (decodedException is CancellationException) {
|
||||||
@ -141,10 +144,8 @@ class _FidoStateNotifier extends FidoStateNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_log.debug('FIDO applet unlock failed');
|
_log.debug('FIDO applet unlock failed');
|
||||||
return PinResult.failed(
|
return PinResult.failed(FidoPinFailureReason.invalidPin(
|
||||||
response['pinRetries'],
|
response['pinRetries'], response['authBlocked']));
|
||||||
response['authBlocked'],
|
|
||||||
);
|
|
||||||
} on PlatformException catch (pe) {
|
} on PlatformException catch (pe) {
|
||||||
var decodedException = pe.decode();
|
var decodedException = pe.decode();
|
||||||
if (decodedException is! CancellationException) {
|
if (decodedException is! CancellationException) {
|
||||||
|
@ -153,7 +153,11 @@ class _DesktopFidoStateNotifier extends FidoStateNotifier {
|
|||||||
return unlock(newPin);
|
return unlock(newPin);
|
||||||
} on RpcError catch (e) {
|
} on RpcError catch (e) {
|
||||||
if (e.status == 'pin-validation') {
|
if (e.status == 'pin-validation') {
|
||||||
return PinResult.failed(e.body['retries'], e.body['auth_blocked']);
|
return PinResult.failed(FidoPinFailureReason.invalidPin(
|
||||||
|
e.body['retries'], e.body['auth_blocked']));
|
||||||
|
}
|
||||||
|
if (e.status == 'pin-complexity') {
|
||||||
|
return PinResult.failed(const FidoPinFailureReason.weakPin());
|
||||||
}
|
}
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
@ -172,7 +176,8 @@ class _DesktopFidoStateNotifier extends FidoStateNotifier {
|
|||||||
} on RpcError catch (e) {
|
} on RpcError catch (e) {
|
||||||
if (e.status == 'pin-validation') {
|
if (e.status == 'pin-validation') {
|
||||||
_pinController.state = null;
|
_pinController.state = null;
|
||||||
return PinResult.failed(e.body['retries'], e.body['auth_blocked']);
|
return PinResult.failed(FidoPinFailureReason.invalidPin(
|
||||||
|
e.body['retries'], e.body['auth_blocked']));
|
||||||
}
|
}
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,12 @@ class _DesktopPivStateNotifier extends PivStateNotifier {
|
|||||||
return const PinVerificationStatus.success();
|
return const PinVerificationStatus.success();
|
||||||
} on RpcError catch (e) {
|
} on RpcError catch (e) {
|
||||||
if (e.status == 'invalid-pin') {
|
if (e.status == 'invalid-pin') {
|
||||||
return PinVerificationStatus.failure(e.body['attempts_remaining']);
|
return PinVerificationStatus.failure(
|
||||||
|
PivPinFailureReason.invalidPin(e.body['attempts_remaining']));
|
||||||
|
}
|
||||||
|
if (e.status == 'pin-complexity') {
|
||||||
|
return PinVerificationStatus.failure(
|
||||||
|
const PivPinFailureReason.weakPin());
|
||||||
}
|
}
|
||||||
rethrow;
|
rethrow;
|
||||||
} finally {
|
} finally {
|
||||||
@ -251,7 +256,12 @@ class _DesktopPivStateNotifier extends PivStateNotifier {
|
|||||||
return const PinVerificationStatus.success();
|
return const PinVerificationStatus.success();
|
||||||
} on RpcError catch (e) {
|
} on RpcError catch (e) {
|
||||||
if (e.status == 'invalid-pin') {
|
if (e.status == 'invalid-pin') {
|
||||||
return PinVerificationStatus.failure(e.body['attempts_remaining']);
|
return PinVerificationStatus.failure(
|
||||||
|
PivPinFailureReason.invalidPin(e.body['attempts_remaining']));
|
||||||
|
}
|
||||||
|
if (e.status == 'pin-complexity') {
|
||||||
|
return PinVerificationStatus.failure(
|
||||||
|
const PivPinFailureReason.weakPin());
|
||||||
}
|
}
|
||||||
rethrow;
|
rethrow;
|
||||||
} finally {
|
} finally {
|
||||||
@ -286,7 +296,12 @@ class _DesktopPivStateNotifier extends PivStateNotifier {
|
|||||||
return const PinVerificationStatus.success();
|
return const PinVerificationStatus.success();
|
||||||
} on RpcError catch (e) {
|
} on RpcError catch (e) {
|
||||||
if (e.status == 'invalid-pin') {
|
if (e.status == 'invalid-pin') {
|
||||||
return PinVerificationStatus.failure(e.body['attempts_remaining']);
|
return PinVerificationStatus.failure(
|
||||||
|
PivPinFailureReason.invalidPin(e.body['attempts_remaining']));
|
||||||
|
}
|
||||||
|
if (e.status == 'pin-complexity') {
|
||||||
|
return PinVerificationStatus.failure(
|
||||||
|
const PivPinFailureReason.weakPin());
|
||||||
}
|
}
|
||||||
rethrow;
|
rethrow;
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -52,7 +52,14 @@ class FidoState with _$FidoState {
|
|||||||
@freezed
|
@freezed
|
||||||
class PinResult with _$PinResult {
|
class PinResult with _$PinResult {
|
||||||
factory PinResult.success() = _PinSuccess;
|
factory PinResult.success() = _PinSuccess;
|
||||||
factory PinResult.failed(int retries, bool authBlocked) = _PinFailure;
|
factory PinResult.failed(FidoPinFailureReason reason) = _PinFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class FidoPinFailureReason with _$FidoPinFailureReason {
|
||||||
|
factory FidoPinFailureReason.invalidPin(int retries, bool authBlocked) =
|
||||||
|
FidoInvalidPin;
|
||||||
|
const factory FidoPinFailureReason.weakPin() = FidoWeakPin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -184,19 +184,19 @@ mixin _$PinResult {
|
|||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult when<TResult extends Object?>({
|
TResult when<TResult extends Object?>({
|
||||||
required TResult Function() success,
|
required TResult Function() success,
|
||||||
required TResult Function(int retries, bool authBlocked) failed,
|
required TResult Function(FidoPinFailureReason reason) failed,
|
||||||
}) =>
|
}) =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult? whenOrNull<TResult extends Object?>({
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
TResult? Function()? success,
|
TResult? Function()? success,
|
||||||
TResult? Function(int retries, bool authBlocked)? failed,
|
TResult? Function(FidoPinFailureReason reason)? failed,
|
||||||
}) =>
|
}) =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult maybeWhen<TResult extends Object?>({
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
TResult Function()? success,
|
TResult Function()? success,
|
||||||
TResult Function(int retries, bool authBlocked)? failed,
|
TResult Function(FidoPinFailureReason reason)? failed,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) =>
|
}) =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
@ -277,7 +277,7 @@ class _$PinSuccessImpl implements _PinSuccess {
|
|||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult when<TResult extends Object?>({
|
TResult when<TResult extends Object?>({
|
||||||
required TResult Function() success,
|
required TResult Function() success,
|
||||||
required TResult Function(int retries, bool authBlocked) failed,
|
required TResult Function(FidoPinFailureReason reason) failed,
|
||||||
}) {
|
}) {
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
@ -286,7 +286,7 @@ class _$PinSuccessImpl implements _PinSuccess {
|
|||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult? whenOrNull<TResult extends Object?>({
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
TResult? Function()? success,
|
TResult? Function()? success,
|
||||||
TResult? Function(int retries, bool authBlocked)? failed,
|
TResult? Function(FidoPinFailureReason reason)? failed,
|
||||||
}) {
|
}) {
|
||||||
return success?.call();
|
return success?.call();
|
||||||
}
|
}
|
||||||
@ -295,7 +295,7 @@ class _$PinSuccessImpl implements _PinSuccess {
|
|||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult maybeWhen<TResult extends Object?>({
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
TResult Function()? success,
|
TResult Function()? success,
|
||||||
TResult Function(int retries, bool authBlocked)? failed,
|
TResult Function(FidoPinFailureReason reason)? failed,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
if (success != null) {
|
if (success != null) {
|
||||||
@ -346,7 +346,9 @@ abstract class _$$PinFailureImplCopyWith<$Res> {
|
|||||||
_$PinFailureImpl value, $Res Function(_$PinFailureImpl) then) =
|
_$PinFailureImpl value, $Res Function(_$PinFailureImpl) then) =
|
||||||
__$$PinFailureImplCopyWithImpl<$Res>;
|
__$$PinFailureImplCopyWithImpl<$Res>;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({int retries, bool authBlocked});
|
$Res call({FidoPinFailureReason reason});
|
||||||
|
|
||||||
|
$FidoPinFailureReasonCopyWith<$Res> get reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -360,35 +362,36 @@ class __$$PinFailureImplCopyWithImpl<$Res>
|
|||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
Object? retries = null,
|
Object? reason = null,
|
||||||
Object? authBlocked = null,
|
|
||||||
}) {
|
}) {
|
||||||
return _then(_$PinFailureImpl(
|
return _then(_$PinFailureImpl(
|
||||||
null == retries
|
null == reason
|
||||||
? _value.retries
|
? _value.reason
|
||||||
: retries // ignore: cast_nullable_to_non_nullable
|
: reason // ignore: cast_nullable_to_non_nullable
|
||||||
as int,
|
as FidoPinFailureReason,
|
||||||
null == authBlocked
|
|
||||||
? _value.authBlocked
|
|
||||||
: authBlocked // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$FidoPinFailureReasonCopyWith<$Res> get reason {
|
||||||
|
return $FidoPinFailureReasonCopyWith<$Res>(_value.reason, (value) {
|
||||||
|
return _then(_value.copyWith(reason: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
|
|
||||||
class _$PinFailureImpl implements _PinFailure {
|
class _$PinFailureImpl implements _PinFailure {
|
||||||
_$PinFailureImpl(this.retries, this.authBlocked);
|
_$PinFailureImpl(this.reason);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final int retries;
|
final FidoPinFailureReason reason;
|
||||||
@override
|
|
||||||
final bool authBlocked;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'PinResult.failed(retries: $retries, authBlocked: $authBlocked)';
|
return 'PinResult.failed(reason: $reason)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -396,13 +399,11 @@ class _$PinFailureImpl implements _PinFailure {
|
|||||||
return identical(this, other) ||
|
return identical(this, other) ||
|
||||||
(other.runtimeType == runtimeType &&
|
(other.runtimeType == runtimeType &&
|
||||||
other is _$PinFailureImpl &&
|
other is _$PinFailureImpl &&
|
||||||
(identical(other.retries, retries) || other.retries == retries) &&
|
(identical(other.reason, reason) || other.reason == reason));
|
||||||
(identical(other.authBlocked, authBlocked) ||
|
|
||||||
other.authBlocked == authBlocked));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType, retries, authBlocked);
|
int get hashCode => Object.hash(runtimeType, reason);
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
@ -414,29 +415,29 @@ class _$PinFailureImpl implements _PinFailure {
|
|||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult when<TResult extends Object?>({
|
TResult when<TResult extends Object?>({
|
||||||
required TResult Function() success,
|
required TResult Function() success,
|
||||||
required TResult Function(int retries, bool authBlocked) failed,
|
required TResult Function(FidoPinFailureReason reason) failed,
|
||||||
}) {
|
}) {
|
||||||
return failed(retries, authBlocked);
|
return failed(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult? whenOrNull<TResult extends Object?>({
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
TResult? Function()? success,
|
TResult? Function()? success,
|
||||||
TResult? Function(int retries, bool authBlocked)? failed,
|
TResult? Function(FidoPinFailureReason reason)? failed,
|
||||||
}) {
|
}) {
|
||||||
return failed?.call(retries, authBlocked);
|
return failed?.call(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult maybeWhen<TResult extends Object?>({
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
TResult Function()? success,
|
TResult Function()? success,
|
||||||
TResult Function(int retries, bool authBlocked)? failed,
|
TResult Function(FidoPinFailureReason reason)? failed,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
if (failed != null) {
|
if (failed != null) {
|
||||||
return failed(retries, authBlocked);
|
return failed(reason);
|
||||||
}
|
}
|
||||||
return orElse();
|
return orElse();
|
||||||
}
|
}
|
||||||
@ -474,16 +475,322 @@ class _$PinFailureImpl implements _PinFailure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class _PinFailure implements PinResult {
|
abstract class _PinFailure implements PinResult {
|
||||||
factory _PinFailure(final int retries, final bool authBlocked) =
|
factory _PinFailure(final FidoPinFailureReason reason) = _$PinFailureImpl;
|
||||||
_$PinFailureImpl;
|
|
||||||
|
FidoPinFailureReason get reason;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
_$$PinFailureImplCopyWith<_$PinFailureImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$FidoPinFailureReason {
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(int retries, bool authBlocked) invalidPin,
|
||||||
|
required TResult Function() weakPin,
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(int retries, bool authBlocked)? invalidPin,
|
||||||
|
TResult? Function()? weakPin,
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(int retries, bool authBlocked)? invalidPin,
|
||||||
|
TResult Function()? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(FidoInvalidPin value) invalidPin,
|
||||||
|
required TResult Function(FidoWeakPin value) weakPin,
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(FidoInvalidPin value)? invalidPin,
|
||||||
|
TResult? Function(FidoWeakPin value)? weakPin,
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(FidoInvalidPin value)? invalidPin,
|
||||||
|
TResult Function(FidoWeakPin value)? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $FidoPinFailureReasonCopyWith<$Res> {
|
||||||
|
factory $FidoPinFailureReasonCopyWith(FidoPinFailureReason value,
|
||||||
|
$Res Function(FidoPinFailureReason) then) =
|
||||||
|
_$FidoPinFailureReasonCopyWithImpl<$Res, FidoPinFailureReason>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$FidoPinFailureReasonCopyWithImpl<$Res,
|
||||||
|
$Val extends FidoPinFailureReason>
|
||||||
|
implements $FidoPinFailureReasonCopyWith<$Res> {
|
||||||
|
_$FidoPinFailureReasonCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$FidoInvalidPinImplCopyWith<$Res> {
|
||||||
|
factory _$$FidoInvalidPinImplCopyWith(_$FidoInvalidPinImpl value,
|
||||||
|
$Res Function(_$FidoInvalidPinImpl) then) =
|
||||||
|
__$$FidoInvalidPinImplCopyWithImpl<$Res>;
|
||||||
|
@useResult
|
||||||
|
$Res call({int retries, bool authBlocked});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$FidoInvalidPinImplCopyWithImpl<$Res>
|
||||||
|
extends _$FidoPinFailureReasonCopyWithImpl<$Res, _$FidoInvalidPinImpl>
|
||||||
|
implements _$$FidoInvalidPinImplCopyWith<$Res> {
|
||||||
|
__$$FidoInvalidPinImplCopyWithImpl(
|
||||||
|
_$FidoInvalidPinImpl _value, $Res Function(_$FidoInvalidPinImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? retries = null,
|
||||||
|
Object? authBlocked = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$FidoInvalidPinImpl(
|
||||||
|
null == retries
|
||||||
|
? _value.retries
|
||||||
|
: retries // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
null == authBlocked
|
||||||
|
? _value.authBlocked
|
||||||
|
: authBlocked // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$FidoInvalidPinImpl implements FidoInvalidPin {
|
||||||
|
_$FidoInvalidPinImpl(this.retries, this.authBlocked);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final int retries;
|
||||||
|
@override
|
||||||
|
final bool authBlocked;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'FidoPinFailureReason.invalidPin(retries: $retries, authBlocked: $authBlocked)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$FidoInvalidPinImpl &&
|
||||||
|
(identical(other.retries, retries) || other.retries == retries) &&
|
||||||
|
(identical(other.authBlocked, authBlocked) ||
|
||||||
|
other.authBlocked == authBlocked));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, retries, authBlocked);
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$FidoInvalidPinImplCopyWith<_$FidoInvalidPinImpl> get copyWith =>
|
||||||
|
__$$FidoInvalidPinImplCopyWithImpl<_$FidoInvalidPinImpl>(
|
||||||
|
this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(int retries, bool authBlocked) invalidPin,
|
||||||
|
required TResult Function() weakPin,
|
||||||
|
}) {
|
||||||
|
return invalidPin(retries, authBlocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(int retries, bool authBlocked)? invalidPin,
|
||||||
|
TResult? Function()? weakPin,
|
||||||
|
}) {
|
||||||
|
return invalidPin?.call(retries, authBlocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(int retries, bool authBlocked)? invalidPin,
|
||||||
|
TResult Function()? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (invalidPin != null) {
|
||||||
|
return invalidPin(retries, authBlocked);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(FidoInvalidPin value) invalidPin,
|
||||||
|
required TResult Function(FidoWeakPin value) weakPin,
|
||||||
|
}) {
|
||||||
|
return invalidPin(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(FidoInvalidPin value)? invalidPin,
|
||||||
|
TResult? Function(FidoWeakPin value)? weakPin,
|
||||||
|
}) {
|
||||||
|
return invalidPin?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(FidoInvalidPin value)? invalidPin,
|
||||||
|
TResult Function(FidoWeakPin value)? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (invalidPin != null) {
|
||||||
|
return invalidPin(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class FidoInvalidPin implements FidoPinFailureReason {
|
||||||
|
factory FidoInvalidPin(final int retries, final bool authBlocked) =
|
||||||
|
_$FidoInvalidPinImpl;
|
||||||
|
|
||||||
int get retries;
|
int get retries;
|
||||||
bool get authBlocked;
|
bool get authBlocked;
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
_$$PinFailureImplCopyWith<_$PinFailureImpl> get copyWith =>
|
_$$FidoInvalidPinImplCopyWith<_$FidoInvalidPinImpl> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$FidoWeakPinImplCopyWith<$Res> {
|
||||||
|
factory _$$FidoWeakPinImplCopyWith(
|
||||||
|
_$FidoWeakPinImpl value, $Res Function(_$FidoWeakPinImpl) then) =
|
||||||
|
__$$FidoWeakPinImplCopyWithImpl<$Res>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$FidoWeakPinImplCopyWithImpl<$Res>
|
||||||
|
extends _$FidoPinFailureReasonCopyWithImpl<$Res, _$FidoWeakPinImpl>
|
||||||
|
implements _$$FidoWeakPinImplCopyWith<$Res> {
|
||||||
|
__$$FidoWeakPinImplCopyWithImpl(
|
||||||
|
_$FidoWeakPinImpl _value, $Res Function(_$FidoWeakPinImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$FidoWeakPinImpl implements FidoWeakPin {
|
||||||
|
const _$FidoWeakPinImpl();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'FidoPinFailureReason.weakPin()';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType && other is _$FidoWeakPinImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(int retries, bool authBlocked) invalidPin,
|
||||||
|
required TResult Function() weakPin,
|
||||||
|
}) {
|
||||||
|
return weakPin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(int retries, bool authBlocked)? invalidPin,
|
||||||
|
TResult? Function()? weakPin,
|
||||||
|
}) {
|
||||||
|
return weakPin?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(int retries, bool authBlocked)? invalidPin,
|
||||||
|
TResult Function()? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (weakPin != null) {
|
||||||
|
return weakPin();
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(FidoInvalidPin value) invalidPin,
|
||||||
|
required TResult Function(FidoWeakPin value) weakPin,
|
||||||
|
}) {
|
||||||
|
return weakPin(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(FidoInvalidPin value)? invalidPin,
|
||||||
|
TResult? Function(FidoWeakPin value)? weakPin,
|
||||||
|
}) {
|
||||||
|
return weakPin?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(FidoInvalidPin value)? invalidPin,
|
||||||
|
TResult Function(FidoWeakPin value)? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (weakPin != null) {
|
||||||
|
return weakPin(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class FidoWeakPin implements FidoPinFailureReason {
|
||||||
|
const factory FidoWeakPin() = _$FidoWeakPinImpl;
|
||||||
|
}
|
||||||
|
|
||||||
Fingerprint _$FingerprintFromJson(Map<String, dynamic> json) {
|
Fingerprint _$FingerprintFromJson(Map<String, dynamic> json) {
|
||||||
return _Fingerprint.fromJson(json);
|
return _Fingerprint.fromJson(json);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,8 @@ class FidoPinDialog extends ConsumerStatefulWidget {
|
|||||||
class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
||||||
final _currentPinController = TextEditingController();
|
final _currentPinController = TextEditingController();
|
||||||
final _currentPinFocus = FocusNode();
|
final _currentPinFocus = FocusNode();
|
||||||
String _newPin = '';
|
final _newPinController = TextEditingController();
|
||||||
|
final _newPinFocus = FocusNode();
|
||||||
String _confirmPin = '';
|
String _confirmPin = '';
|
||||||
String? _currentPinError;
|
String? _currentPinError;
|
||||||
String? _newPinError;
|
String? _newPinError;
|
||||||
@ -63,6 +64,8 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
|||||||
void dispose() {
|
void dispose() {
|
||||||
_currentPinController.dispose();
|
_currentPinController.dispose();
|
||||||
_currentPinFocus.dispose();
|
_currentPinFocus.dispose();
|
||||||
|
_newPinController.dispose();
|
||||||
|
_newPinFocus.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,8 +80,13 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
|||||||
: (widget.state.forcePinChange ? 4 : widget.state.minPinLength);
|
: (widget.state.forcePinChange ? 4 : widget.state.minPinLength);
|
||||||
final currentPinLenOk =
|
final currentPinLenOk =
|
||||||
_currentPinController.text.length >= currentMinPinLen;
|
_currentPinController.text.length >= currentMinPinLen;
|
||||||
final newPinLenOk = _newPin.length >= minPinLength;
|
final newPinLenOk = _newPinController.text.length >= minPinLength;
|
||||||
final isValid = currentPinLenOk && newPinLenOk && _newPin == _confirmPin;
|
final isValid =
|
||||||
|
currentPinLenOk && newPinLenOk && _newPinController.text == _confirmPin;
|
||||||
|
|
||||||
|
final hasPinComplexity =
|
||||||
|
ref.read(currentDeviceDataProvider).valueOrNull?.info.pinComplexity ??
|
||||||
|
false;
|
||||||
|
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(hasPin ? l10n.s_change_pin : l10n.s_set_pin),
|
title: Text(hasPin ? l10n.s_change_pin : l10n.s_set_pin),
|
||||||
@ -130,11 +138,15 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
|||||||
},
|
},
|
||||||
).init(),
|
).init(),
|
||||||
],
|
],
|
||||||
Text(l10n.p_enter_new_fido2_pin(minPinLength)),
|
Text(hasPinComplexity
|
||||||
|
? l10n.p_enter_new_fido2_pin_complexity_active(
|
||||||
|
minPinLength, 2, '123456')
|
||||||
|
: l10n.p_enter_new_fido2_pin(minPinLength)),
|
||||||
// TODO: Set max characters based on UTF-8 bytes
|
// TODO: Set max characters based on UTF-8 bytes
|
||||||
AppTextFormField(
|
AppTextFormField(
|
||||||
key: newPin,
|
key: newPin,
|
||||||
initialValue: _newPin,
|
controller: _newPinController,
|
||||||
|
focusNode: _newPinFocus,
|
||||||
autofocus: !hasPin,
|
autofocus: !hasPin,
|
||||||
obscureText: _isObscureNew,
|
obscureText: _isObscureNew,
|
||||||
autofillHints: const [AutofillHints.password],
|
autofillHints: const [AutofillHints.password],
|
||||||
@ -160,7 +172,6 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
|||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_newIsWrong = false;
|
_newIsWrong = false;
|
||||||
_newPin = value;
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
).init(),
|
).init(),
|
||||||
@ -186,10 +197,11 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
|||||||
_isObscureConfirm ? l10n.s_show_pin : l10n.s_hide_pin,
|
_isObscureConfirm ? l10n.s_show_pin : l10n.s_hide_pin,
|
||||||
),
|
),
|
||||||
enabled: !_isBlocked && currentPinLenOk && newPinLenOk,
|
enabled: !_isBlocked && currentPinLenOk && newPinLenOk,
|
||||||
errorText: _newPin.length == _confirmPin.length &&
|
errorText:
|
||||||
_newPin != _confirmPin
|
_newPinController.text.length == _confirmPin.length &&
|
||||||
? l10n.l_pin_mismatch
|
_newPinController.text != _confirmPin
|
||||||
: null,
|
? l10n.l_pin_mismatch
|
||||||
|
: null,
|
||||||
helperText: '', // Prevents resizing when errorText shown
|
helperText: '', // Prevents resizing when errorText shown
|
||||||
),
|
),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -219,28 +231,47 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
|||||||
final oldPin = _currentPinController.text.isNotEmpty
|
final oldPin = _currentPinController.text.isNotEmpty
|
||||||
? _currentPinController.text
|
? _currentPinController.text
|
||||||
: null;
|
: null;
|
||||||
|
final newPin = _newPinController.text;
|
||||||
try {
|
try {
|
||||||
final result = await ref
|
final result = await ref
|
||||||
.read(fidoStateProvider(widget.devicePath).notifier)
|
.read(fidoStateProvider(widget.devicePath).notifier)
|
||||||
.setPin(_newPin, oldPin: oldPin);
|
.setPin(newPin, oldPin: oldPin);
|
||||||
result.when(success: () {
|
result.whenOrNull(
|
||||||
Navigator.of(context).pop(true);
|
success: () {
|
||||||
showMessage(context, l10n.s_pin_set);
|
Navigator.of(context).pop(true);
|
||||||
}, failed: (retries, authBlocked) {
|
showMessage(context, l10n.s_pin_set);
|
||||||
setState(() {
|
},
|
||||||
_currentPinController.selection = TextSelection(
|
failed: (reason) {
|
||||||
baseOffset: 0, extentOffset: _currentPinController.text.length);
|
reason.when(
|
||||||
_currentPinFocus.requestFocus();
|
invalidPin: (retries, authBlocked) {
|
||||||
if (authBlocked) {
|
_currentPinController.selection = TextSelection(
|
||||||
_currentPinError = l10n.l_pin_soft_locked;
|
baseOffset: 0,
|
||||||
_currentIsWrong = true;
|
extentOffset: _currentPinController.text.length);
|
||||||
_isBlocked = true;
|
_currentPinFocus.requestFocus();
|
||||||
} else {
|
setState(() {
|
||||||
_currentPinError = l10n.l_wrong_pin_attempts_remaining(retries);
|
if (authBlocked) {
|
||||||
_currentIsWrong = true;
|
_currentPinError = l10n.l_pin_soft_locked;
|
||||||
}
|
_currentIsWrong = true;
|
||||||
});
|
_isBlocked = true;
|
||||||
});
|
} else {
|
||||||
|
_currentPinError =
|
||||||
|
l10n.l_wrong_pin_attempts_remaining(retries);
|
||||||
|
_currentIsWrong = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
weakPin: () {
|
||||||
|
_newPinController.selection = TextSelection(
|
||||||
|
baseOffset: 0, extentOffset: _newPinController.text.length);
|
||||||
|
_newPinFocus.requestFocus();
|
||||||
|
setState(() {
|
||||||
|
_newPinError = l10n.p_pin_puk_complexity_failure(l10n.s_pin);
|
||||||
|
_newIsWrong = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
} on CancellationException catch (_) {
|
} on CancellationException catch (_) {
|
||||||
// ignored
|
// ignored
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -60,15 +60,20 @@ class _PinEntryFormState extends ConsumerState<PinEntryForm> {
|
|||||||
final result = await ref
|
final result = await ref
|
||||||
.read(fidoStateProvider(widget._deviceNode.path).notifier)
|
.read(fidoStateProvider(widget._deviceNode.path).notifier)
|
||||||
.unlock(_pinController.text);
|
.unlock(_pinController.text);
|
||||||
result.whenOrNull(failed: (retries, authBlocked) {
|
result.whenOrNull(failed: (reason) {
|
||||||
_pinController.selection = TextSelection(
|
reason.maybeWhen(
|
||||||
baseOffset: 0, extentOffset: _pinController.text.length);
|
invalidPin: (retries, authBlocked) {
|
||||||
_pinFocus.requestFocus();
|
_pinController.selection = TextSelection(
|
||||||
setState(() {
|
baseOffset: 0, extentOffset: _pinController.text.length);
|
||||||
_pinIsWrong = true;
|
_pinFocus.requestFocus();
|
||||||
_retries = retries;
|
setState(() {
|
||||||
_blocked = authBlocked;
|
_pinIsWrong = true;
|
||||||
});
|
_retries = retries;
|
||||||
|
_blocked = authBlocked;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
orElse: () {},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
} on CancellationException catch (_) {
|
} on CancellationException catch (_) {
|
||||||
// ignored
|
// ignored
|
||||||
|
@ -252,6 +252,18 @@
|
|||||||
"message": {}
|
"message": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"l_set_puk_failed": null,
|
||||||
|
"@l_set_puk_failed": {
|
||||||
|
"placeholders": {
|
||||||
|
"message": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"l_unblock_pin_failed": null,
|
||||||
|
"@l_unblock_pin_failed": {
|
||||||
|
"placeholders": {
|
||||||
|
"message": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"l_attempts_remaining": null,
|
"l_attempts_remaining": null,
|
||||||
"@l_attempts_remaining": {
|
"@l_attempts_remaining": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
@ -288,6 +300,14 @@
|
|||||||
"length": {}
|
"length": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"p_enter_new_fido2_pin_complexity_active": null,
|
||||||
|
"@p_enter_new_fido2_pin_complexity_active": {
|
||||||
|
"placeholders": {
|
||||||
|
"length": {},
|
||||||
|
"unique_characters": {},
|
||||||
|
"common_pin": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"s_pin_required": null,
|
"s_pin_required": null,
|
||||||
"p_pin_required_desc": null,
|
"p_pin_required_desc": null,
|
||||||
"l_piv_pin_blocked": null,
|
"l_piv_pin_blocked": null,
|
||||||
@ -298,6 +318,19 @@
|
|||||||
"name": {}
|
"name": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"p_enter_new_piv_pin_puk_complexity_active": null,
|
||||||
|
"@p_enter_new_piv_pin_puk_complexity_active": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {},
|
||||||
|
"common": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"p_pin_puk_complexity_failure": null,
|
||||||
|
"@p_pin_puk_complexity_failure": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"l_warning_default_pin": null,
|
"l_warning_default_pin": null,
|
||||||
"l_warning_default_puk": null,
|
"l_warning_default_puk": null,
|
||||||
"l_default_pin_used": null,
|
"l_default_pin_used": null,
|
||||||
|
@ -252,6 +252,18 @@
|
|||||||
"message": {}
|
"message": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"l_set_puk_failed": "Failed to set PUK: {message}",
|
||||||
|
"@l_set_puk_failed": {
|
||||||
|
"placeholders": {
|
||||||
|
"message": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"l_unblock_pin_failed": "Failed to unblock PIN: {message}",
|
||||||
|
"@l_unblock_pin_failed": {
|
||||||
|
"placeholders": {
|
||||||
|
"message": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"l_attempts_remaining": "{retries} attempt(s) remaining",
|
"l_attempts_remaining": "{retries} attempt(s) remaining",
|
||||||
"@l_attempts_remaining": {
|
"@l_attempts_remaining": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
@ -288,6 +300,14 @@
|
|||||||
"length": {}
|
"length": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"p_enter_new_fido2_pin_complexity_active": "Enter your new PIN. A PIN must be at least {length} characters long, contain at least {unique_characters} unique characters, and not be a commonly used PIN, like \"{common_pin}\". It may contain letters, numbers, and special characters.",
|
||||||
|
"@p_enter_new_fido2_pin_complexity_active": {
|
||||||
|
"placeholders": {
|
||||||
|
"length": {},
|
||||||
|
"unique_characters": {},
|
||||||
|
"common_pin": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"s_pin_required": "PIN required",
|
"s_pin_required": "PIN required",
|
||||||
"p_pin_required_desc": "The action you are about to perform requires the PIV PIN to be entered.",
|
"p_pin_required_desc": "The action you are about to perform requires the PIV PIN to be entered.",
|
||||||
"l_piv_pin_blocked": "Blocked, use PUK to reset",
|
"l_piv_pin_blocked": "Blocked, use PUK to reset",
|
||||||
@ -298,6 +318,19 @@
|
|||||||
"name": {}
|
"name": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"p_enter_new_piv_pin_puk_complexity_active": "Enter a new {name} to set. Must be 6-8 characters, contain at least 2 unique characters, and not be a commonly used {name}, like \"{common}\".",
|
||||||
|
"@p_enter_new_piv_pin_puk_complexity_active": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {},
|
||||||
|
"common": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"p_pin_puk_complexity_failure": "New {name} doesn't meet complexity requirements.",
|
||||||
|
"@p_pin_puk_complexity_failure": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"l_warning_default_pin": "Warning: Default PIN used",
|
"l_warning_default_pin": "Warning: Default PIN used",
|
||||||
"l_warning_default_puk": "Warning: Default PUK used",
|
"l_warning_default_puk": "Warning: Default PUK used",
|
||||||
"l_default_pin_used": "Default PIN used",
|
"l_default_pin_used": "Default PIN used",
|
||||||
|
@ -252,6 +252,18 @@
|
|||||||
"message": {}
|
"message": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"l_set_puk_failed": null,
|
||||||
|
"@l_set_puk_failed": {
|
||||||
|
"placeholders": {
|
||||||
|
"message": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"l_unblock_pin_failed": null,
|
||||||
|
"@l_unblock_pin_failed": {
|
||||||
|
"placeholders": {
|
||||||
|
"message": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"l_attempts_remaining": "Nombre de tentative(s) restante(s) : {retries}",
|
"l_attempts_remaining": "Nombre de tentative(s) restante(s) : {retries}",
|
||||||
"@l_attempts_remaining": {
|
"@l_attempts_remaining": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
@ -288,6 +300,14 @@
|
|||||||
"length": {}
|
"length": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"p_enter_new_fido2_pin_complexity_active": null,
|
||||||
|
"@p_enter_new_fido2_pin_complexity_active": {
|
||||||
|
"placeholders": {
|
||||||
|
"length": {},
|
||||||
|
"unique_characters": {},
|
||||||
|
"common_pin": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"s_pin_required": "PIN requis",
|
"s_pin_required": "PIN requis",
|
||||||
"p_pin_required_desc": "L'action que vous allez faire demande d'entrer le code PIN du PIV.",
|
"p_pin_required_desc": "L'action que vous allez faire demande d'entrer le code PIN du PIV.",
|
||||||
"l_piv_pin_blocked": "Vous êtes bloqué, utilisez le code PUK pour réinitialiser",
|
"l_piv_pin_blocked": "Vous êtes bloqué, utilisez le code PUK pour réinitialiser",
|
||||||
@ -298,6 +318,19 @@
|
|||||||
"name": {}
|
"name": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"p_enter_new_piv_pin_puk_complexity_active": null,
|
||||||
|
"@p_enter_new_piv_pin_puk_complexity_active": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {},
|
||||||
|
"common": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"p_pin_puk_complexity_failure": null,
|
||||||
|
"@p_pin_puk_complexity_failure": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"l_warning_default_pin": null,
|
"l_warning_default_pin": null,
|
||||||
"l_warning_default_puk": null,
|
"l_warning_default_puk": null,
|
||||||
"l_default_pin_used": null,
|
"l_default_pin_used": null,
|
||||||
|
@ -252,6 +252,18 @@
|
|||||||
"message": {}
|
"message": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"l_set_puk_failed": null,
|
||||||
|
"@l_set_puk_failed": {
|
||||||
|
"placeholders": {
|
||||||
|
"message": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"l_unblock_pin_failed": null,
|
||||||
|
"@l_unblock_pin_failed": {
|
||||||
|
"placeholders": {
|
||||||
|
"message": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"l_attempts_remaining": "あと{retries}回試行できます",
|
"l_attempts_remaining": "あと{retries}回試行できます",
|
||||||
"@l_attempts_remaining": {
|
"@l_attempts_remaining": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
@ -288,6 +300,14 @@
|
|||||||
"length": {}
|
"length": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"p_enter_new_fido2_pin_complexity_active": null,
|
||||||
|
"@p_enter_new_fido2_pin_complexity_active": {
|
||||||
|
"placeholders": {
|
||||||
|
"length": {},
|
||||||
|
"unique_characters": {},
|
||||||
|
"common_pin": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"s_pin_required": "PINが必要",
|
"s_pin_required": "PINが必要",
|
||||||
"p_pin_required_desc": "実行しようとしている操作には、PIV PINの入力が必要です",
|
"p_pin_required_desc": "実行しようとしている操作には、PIV PINの入力が必要です",
|
||||||
"l_piv_pin_blocked": "ブロックされています。PUK を使用してリセットしてください",
|
"l_piv_pin_blocked": "ブロックされています。PUK を使用してリセットしてください",
|
||||||
@ -298,6 +318,19 @@
|
|||||||
"name": {}
|
"name": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"p_enter_new_piv_pin_puk_complexity_active": null,
|
||||||
|
"@p_enter_new_piv_pin_puk_complexity_active": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {},
|
||||||
|
"common": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"p_pin_puk_complexity_failure": null,
|
||||||
|
"@p_pin_puk_complexity_failure": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"l_warning_default_pin": null,
|
"l_warning_default_pin": null,
|
||||||
"l_warning_default_puk": null,
|
"l_warning_default_puk": null,
|
||||||
"l_default_pin_used": null,
|
"l_default_pin_used": null,
|
||||||
|
@ -252,6 +252,18 @@
|
|||||||
"message": {}
|
"message": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"l_set_puk_failed": null,
|
||||||
|
"@l_set_puk_failed": {
|
||||||
|
"placeholders": {
|
||||||
|
"message": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"l_unblock_pin_failed": null,
|
||||||
|
"@l_unblock_pin_failed": {
|
||||||
|
"placeholders": {
|
||||||
|
"message": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"l_attempts_remaining": "Pozostało prób: {retries}",
|
"l_attempts_remaining": "Pozostało prób: {retries}",
|
||||||
"@l_attempts_remaining": {
|
"@l_attempts_remaining": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
@ -288,6 +300,14 @@
|
|||||||
"length": {}
|
"length": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"p_enter_new_fido2_pin_complexity_active": null,
|
||||||
|
"@p_enter_new_fido2_pin_complexity_active": {
|
||||||
|
"placeholders": {
|
||||||
|
"length": {},
|
||||||
|
"unique_characters": {},
|
||||||
|
"common_pin": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"s_pin_required": "Wymagany PIN",
|
"s_pin_required": "Wymagany PIN",
|
||||||
"p_pin_required_desc": "Czynność, którą zamierzasz wykonać, wymaga wprowadzenia kodu PIN PIV.",
|
"p_pin_required_desc": "Czynność, którą zamierzasz wykonać, wymaga wprowadzenia kodu PIN PIV.",
|
||||||
"l_piv_pin_blocked": "Zablokowano, użyj PUK, aby zresetować",
|
"l_piv_pin_blocked": "Zablokowano, użyj PUK, aby zresetować",
|
||||||
@ -298,6 +318,19 @@
|
|||||||
"name": {}
|
"name": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"p_enter_new_piv_pin_puk_complexity_active": null,
|
||||||
|
"@p_enter_new_piv_pin_puk_complexity_active": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {},
|
||||||
|
"common": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"p_pin_puk_complexity_failure": null,
|
||||||
|
"@p_pin_puk_complexity_failure": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"l_warning_default_pin": null,
|
"l_warning_default_pin": null,
|
||||||
"l_warning_default_puk": null,
|
"l_warning_default_puk": null,
|
||||||
"l_default_pin_used": null,
|
"l_default_pin_used": null,
|
||||||
|
@ -86,7 +86,8 @@ class DeviceInfo with _$DeviceInfo {
|
|||||||
Map<Transport, int> supportedCapabilities,
|
Map<Transport, int> supportedCapabilities,
|
||||||
bool isLocked,
|
bool isLocked,
|
||||||
bool isFips,
|
bool isFips,
|
||||||
bool isSky) = _DeviceInfo;
|
bool isSky,
|
||||||
|
bool pinComplexity) = _DeviceInfo;
|
||||||
|
|
||||||
factory DeviceInfo.fromJson(Map<String, dynamic> json) =>
|
factory DeviceInfo.fromJson(Map<String, dynamic> json) =>
|
||||||
_$DeviceInfoFromJson(json);
|
_$DeviceInfoFromJson(json);
|
||||||
|
@ -245,6 +245,7 @@ mixin _$DeviceInfo {
|
|||||||
bool get isLocked => throw _privateConstructorUsedError;
|
bool get isLocked => throw _privateConstructorUsedError;
|
||||||
bool get isFips => throw _privateConstructorUsedError;
|
bool get isFips => throw _privateConstructorUsedError;
|
||||||
bool get isSky => throw _privateConstructorUsedError;
|
bool get isSky => throw _privateConstructorUsedError;
|
||||||
|
bool get pinComplexity => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@ -266,7 +267,8 @@ abstract class $DeviceInfoCopyWith<$Res> {
|
|||||||
Map<Transport, int> supportedCapabilities,
|
Map<Transport, int> supportedCapabilities,
|
||||||
bool isLocked,
|
bool isLocked,
|
||||||
bool isFips,
|
bool isFips,
|
||||||
bool isSky});
|
bool isSky,
|
||||||
|
bool pinComplexity});
|
||||||
|
|
||||||
$DeviceConfigCopyWith<$Res> get config;
|
$DeviceConfigCopyWith<$Res> get config;
|
||||||
$VersionCopyWith<$Res> get version;
|
$VersionCopyWith<$Res> get version;
|
||||||
@ -293,6 +295,7 @@ class _$DeviceInfoCopyWithImpl<$Res, $Val extends DeviceInfo>
|
|||||||
Object? isLocked = null,
|
Object? isLocked = null,
|
||||||
Object? isFips = null,
|
Object? isFips = null,
|
||||||
Object? isSky = null,
|
Object? isSky = null,
|
||||||
|
Object? pinComplexity = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_value.copyWith(
|
return _then(_value.copyWith(
|
||||||
config: null == config
|
config: null == config
|
||||||
@ -327,6 +330,10 @@ class _$DeviceInfoCopyWithImpl<$Res, $Val extends DeviceInfo>
|
|||||||
? _value.isSky
|
? _value.isSky
|
||||||
: isSky // ignore: cast_nullable_to_non_nullable
|
: isSky // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
pinComplexity: null == pinComplexity
|
||||||
|
? _value.pinComplexity
|
||||||
|
: pinComplexity // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
) as $Val);
|
) as $Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,7 +370,8 @@ abstract class _$$DeviceInfoImplCopyWith<$Res>
|
|||||||
Map<Transport, int> supportedCapabilities,
|
Map<Transport, int> supportedCapabilities,
|
||||||
bool isLocked,
|
bool isLocked,
|
||||||
bool isFips,
|
bool isFips,
|
||||||
bool isSky});
|
bool isSky,
|
||||||
|
bool pinComplexity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
$DeviceConfigCopyWith<$Res> get config;
|
$DeviceConfigCopyWith<$Res> get config;
|
||||||
@ -390,6 +398,7 @@ class __$$DeviceInfoImplCopyWithImpl<$Res>
|
|||||||
Object? isLocked = null,
|
Object? isLocked = null,
|
||||||
Object? isFips = null,
|
Object? isFips = null,
|
||||||
Object? isSky = null,
|
Object? isSky = null,
|
||||||
|
Object? pinComplexity = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_$DeviceInfoImpl(
|
return _then(_$DeviceInfoImpl(
|
||||||
null == config
|
null == config
|
||||||
@ -424,6 +433,10 @@ class __$$DeviceInfoImplCopyWithImpl<$Res>
|
|||||||
? _value.isSky
|
? _value.isSky
|
||||||
: isSky // ignore: cast_nullable_to_non_nullable
|
: isSky // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
null == pinComplexity
|
||||||
|
? _value.pinComplexity
|
||||||
|
: pinComplexity // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -439,7 +452,8 @@ class _$DeviceInfoImpl implements _DeviceInfo {
|
|||||||
final Map<Transport, int> supportedCapabilities,
|
final Map<Transport, int> supportedCapabilities,
|
||||||
this.isLocked,
|
this.isLocked,
|
||||||
this.isFips,
|
this.isFips,
|
||||||
this.isSky)
|
this.isSky,
|
||||||
|
this.pinComplexity)
|
||||||
: _supportedCapabilities = supportedCapabilities;
|
: _supportedCapabilities = supportedCapabilities;
|
||||||
|
|
||||||
factory _$DeviceInfoImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$DeviceInfoImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
@ -468,10 +482,12 @@ class _$DeviceInfoImpl implements _DeviceInfo {
|
|||||||
final bool isFips;
|
final bool isFips;
|
||||||
@override
|
@override
|
||||||
final bool isSky;
|
final bool isSky;
|
||||||
|
@override
|
||||||
|
final bool pinComplexity;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'DeviceInfo(config: $config, serial: $serial, version: $version, formFactor: $formFactor, supportedCapabilities: $supportedCapabilities, isLocked: $isLocked, isFips: $isFips, isSky: $isSky)';
|
return 'DeviceInfo(config: $config, serial: $serial, version: $version, formFactor: $formFactor, supportedCapabilities: $supportedCapabilities, isLocked: $isLocked, isFips: $isFips, isSky: $isSky, pinComplexity: $pinComplexity)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -489,7 +505,9 @@ class _$DeviceInfoImpl implements _DeviceInfo {
|
|||||||
(identical(other.isLocked, isLocked) ||
|
(identical(other.isLocked, isLocked) ||
|
||||||
other.isLocked == isLocked) &&
|
other.isLocked == isLocked) &&
|
||||||
(identical(other.isFips, isFips) || other.isFips == isFips) &&
|
(identical(other.isFips, isFips) || other.isFips == isFips) &&
|
||||||
(identical(other.isSky, isSky) || other.isSky == isSky));
|
(identical(other.isSky, isSky) || other.isSky == isSky) &&
|
||||||
|
(identical(other.pinComplexity, pinComplexity) ||
|
||||||
|
other.pinComplexity == pinComplexity));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@ -503,7 +521,8 @@ class _$DeviceInfoImpl implements _DeviceInfo {
|
|||||||
const DeepCollectionEquality().hash(_supportedCapabilities),
|
const DeepCollectionEquality().hash(_supportedCapabilities),
|
||||||
isLocked,
|
isLocked,
|
||||||
isFips,
|
isFips,
|
||||||
isSky);
|
isSky,
|
||||||
|
pinComplexity);
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
@ -528,7 +547,8 @@ abstract class _DeviceInfo implements DeviceInfo {
|
|||||||
final Map<Transport, int> supportedCapabilities,
|
final Map<Transport, int> supportedCapabilities,
|
||||||
final bool isLocked,
|
final bool isLocked,
|
||||||
final bool isFips,
|
final bool isFips,
|
||||||
final bool isSky) = _$DeviceInfoImpl;
|
final bool isSky,
|
||||||
|
final bool pinComplexity) = _$DeviceInfoImpl;
|
||||||
|
|
||||||
factory _DeviceInfo.fromJson(Map<String, dynamic> json) =
|
factory _DeviceInfo.fromJson(Map<String, dynamic> json) =
|
||||||
_$DeviceInfoImpl.fromJson;
|
_$DeviceInfoImpl.fromJson;
|
||||||
@ -550,6 +570,8 @@ abstract class _DeviceInfo implements DeviceInfo {
|
|||||||
@override
|
@override
|
||||||
bool get isSky;
|
bool get isSky;
|
||||||
@override
|
@override
|
||||||
|
bool get pinComplexity;
|
||||||
|
@override
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
_$$DeviceInfoImplCopyWith<_$DeviceInfoImpl> get copyWith =>
|
_$$DeviceInfoImplCopyWith<_$DeviceInfoImpl> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
|
@ -42,6 +42,7 @@ _$DeviceInfoImpl _$$DeviceInfoImplFromJson(Map<String, dynamic> json) =>
|
|||||||
json['is_locked'] as bool,
|
json['is_locked'] as bool,
|
||||||
json['is_fips'] as bool,
|
json['is_fips'] as bool,
|
||||||
json['is_sky'] as bool,
|
json['is_sky'] as bool,
|
||||||
|
json['pin_complexity'] as bool,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$DeviceInfoImplToJson(_$DeviceInfoImpl instance) =>
|
Map<String, dynamic> _$$DeviceInfoImplToJson(_$DeviceInfoImpl instance) =>
|
||||||
@ -55,6 +56,7 @@ Map<String, dynamic> _$$DeviceInfoImplToJson(_$DeviceInfoImpl instance) =>
|
|||||||
'is_locked': instance.isLocked,
|
'is_locked': instance.isLocked,
|
||||||
'is_fips': instance.isFips,
|
'is_fips': instance.isFips,
|
||||||
'is_sky': instance.isSky,
|
'is_sky': instance.isSky,
|
||||||
|
'pin_complexity': instance.pinComplexity,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$FormFactorEnumMap = {
|
const _$FormFactorEnumMap = {
|
||||||
|
@ -209,7 +209,14 @@ class PinMetadata with _$PinMetadata {
|
|||||||
@freezed
|
@freezed
|
||||||
class PinVerificationStatus with _$PinVerificationStatus {
|
class PinVerificationStatus with _$PinVerificationStatus {
|
||||||
const factory PinVerificationStatus.success() = PinSuccess;
|
const factory PinVerificationStatus.success() = PinSuccess;
|
||||||
factory PinVerificationStatus.failure(int attemptsRemaining) = PinFailure;
|
factory PinVerificationStatus.failure(PivPinFailureReason reason) =
|
||||||
|
PinFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class PivPinFailureReason with _$PivPinFailureReason {
|
||||||
|
factory PivPinFailureReason.invalidPin(int attemptsRemaining) = PivInvalidPin;
|
||||||
|
const factory PivPinFailureReason.weakPin() = PivWeakPin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -193,19 +193,19 @@ mixin _$PinVerificationStatus {
|
|||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult when<TResult extends Object?>({
|
TResult when<TResult extends Object?>({
|
||||||
required TResult Function() success,
|
required TResult Function() success,
|
||||||
required TResult Function(int attemptsRemaining) failure,
|
required TResult Function(PivPinFailureReason reason) failure,
|
||||||
}) =>
|
}) =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult? whenOrNull<TResult extends Object?>({
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
TResult? Function()? success,
|
TResult? Function()? success,
|
||||||
TResult? Function(int attemptsRemaining)? failure,
|
TResult? Function(PivPinFailureReason reason)? failure,
|
||||||
}) =>
|
}) =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult maybeWhen<TResult extends Object?>({
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
TResult Function()? success,
|
TResult Function()? success,
|
||||||
TResult Function(int attemptsRemaining)? failure,
|
TResult Function(PivPinFailureReason reason)? failure,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) =>
|
}) =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
@ -288,7 +288,7 @@ class _$PinSuccessImpl implements PinSuccess {
|
|||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult when<TResult extends Object?>({
|
TResult when<TResult extends Object?>({
|
||||||
required TResult Function() success,
|
required TResult Function() success,
|
||||||
required TResult Function(int attemptsRemaining) failure,
|
required TResult Function(PivPinFailureReason reason) failure,
|
||||||
}) {
|
}) {
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
@ -297,7 +297,7 @@ class _$PinSuccessImpl implements PinSuccess {
|
|||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult? whenOrNull<TResult extends Object?>({
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
TResult? Function()? success,
|
TResult? Function()? success,
|
||||||
TResult? Function(int attemptsRemaining)? failure,
|
TResult? Function(PivPinFailureReason reason)? failure,
|
||||||
}) {
|
}) {
|
||||||
return success?.call();
|
return success?.call();
|
||||||
}
|
}
|
||||||
@ -306,7 +306,7 @@ class _$PinSuccessImpl implements PinSuccess {
|
|||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult maybeWhen<TResult extends Object?>({
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
TResult Function()? success,
|
TResult Function()? success,
|
||||||
TResult Function(int attemptsRemaining)? failure,
|
TResult Function(PivPinFailureReason reason)? failure,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
if (success != null) {
|
if (success != null) {
|
||||||
@ -357,7 +357,9 @@ abstract class _$$PinFailureImplCopyWith<$Res> {
|
|||||||
_$PinFailureImpl value, $Res Function(_$PinFailureImpl) then) =
|
_$PinFailureImpl value, $Res Function(_$PinFailureImpl) then) =
|
||||||
__$$PinFailureImplCopyWithImpl<$Res>;
|
__$$PinFailureImplCopyWithImpl<$Res>;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({int attemptsRemaining});
|
$Res call({PivPinFailureReason reason});
|
||||||
|
|
||||||
|
$PivPinFailureReasonCopyWith<$Res> get reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -371,28 +373,36 @@ class __$$PinFailureImplCopyWithImpl<$Res>
|
|||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
Object? attemptsRemaining = null,
|
Object? reason = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_$PinFailureImpl(
|
return _then(_$PinFailureImpl(
|
||||||
null == attemptsRemaining
|
null == reason
|
||||||
? _value.attemptsRemaining
|
? _value.reason
|
||||||
: attemptsRemaining // ignore: cast_nullable_to_non_nullable
|
: reason // ignore: cast_nullable_to_non_nullable
|
||||||
as int,
|
as PivPinFailureReason,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$PivPinFailureReasonCopyWith<$Res> get reason {
|
||||||
|
return $PivPinFailureReasonCopyWith<$Res>(_value.reason, (value) {
|
||||||
|
return _then(_value.copyWith(reason: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
|
|
||||||
class _$PinFailureImpl implements PinFailure {
|
class _$PinFailureImpl implements PinFailure {
|
||||||
_$PinFailureImpl(this.attemptsRemaining);
|
_$PinFailureImpl(this.reason);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final int attemptsRemaining;
|
final PivPinFailureReason reason;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'PinVerificationStatus.failure(attemptsRemaining: $attemptsRemaining)';
|
return 'PinVerificationStatus.failure(reason: $reason)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -400,12 +410,11 @@ class _$PinFailureImpl implements PinFailure {
|
|||||||
return identical(this, other) ||
|
return identical(this, other) ||
|
||||||
(other.runtimeType == runtimeType &&
|
(other.runtimeType == runtimeType &&
|
||||||
other is _$PinFailureImpl &&
|
other is _$PinFailureImpl &&
|
||||||
(identical(other.attemptsRemaining, attemptsRemaining) ||
|
(identical(other.reason, reason) || other.reason == reason));
|
||||||
other.attemptsRemaining == attemptsRemaining));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType, attemptsRemaining);
|
int get hashCode => Object.hash(runtimeType, reason);
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
@ -417,29 +426,29 @@ class _$PinFailureImpl implements PinFailure {
|
|||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult when<TResult extends Object?>({
|
TResult when<TResult extends Object?>({
|
||||||
required TResult Function() success,
|
required TResult Function() success,
|
||||||
required TResult Function(int attemptsRemaining) failure,
|
required TResult Function(PivPinFailureReason reason) failure,
|
||||||
}) {
|
}) {
|
||||||
return failure(attemptsRemaining);
|
return failure(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult? whenOrNull<TResult extends Object?>({
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
TResult? Function()? success,
|
TResult? Function()? success,
|
||||||
TResult? Function(int attemptsRemaining)? failure,
|
TResult? Function(PivPinFailureReason reason)? failure,
|
||||||
}) {
|
}) {
|
||||||
return failure?.call(attemptsRemaining);
|
return failure?.call(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult maybeWhen<TResult extends Object?>({
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
TResult Function()? success,
|
TResult Function()? success,
|
||||||
TResult Function(int attemptsRemaining)? failure,
|
TResult Function(PivPinFailureReason reason)? failure,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
if (failure != null) {
|
if (failure != null) {
|
||||||
return failure(attemptsRemaining);
|
return failure(reason);
|
||||||
}
|
}
|
||||||
return orElse();
|
return orElse();
|
||||||
}
|
}
|
||||||
@ -477,14 +486,310 @@ class _$PinFailureImpl implements PinFailure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class PinFailure implements PinVerificationStatus {
|
abstract class PinFailure implements PinVerificationStatus {
|
||||||
factory PinFailure(final int attemptsRemaining) = _$PinFailureImpl;
|
factory PinFailure(final PivPinFailureReason reason) = _$PinFailureImpl;
|
||||||
|
|
||||||
int get attemptsRemaining;
|
PivPinFailureReason get reason;
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
_$$PinFailureImplCopyWith<_$PinFailureImpl> get copyWith =>
|
_$$PinFailureImplCopyWith<_$PinFailureImpl> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$PivPinFailureReason {
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(int attemptsRemaining) invalidPin,
|
||||||
|
required TResult Function() weakPin,
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(int attemptsRemaining)? invalidPin,
|
||||||
|
TResult? Function()? weakPin,
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(int attemptsRemaining)? invalidPin,
|
||||||
|
TResult Function()? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(PivInvalidPin value) invalidPin,
|
||||||
|
required TResult Function(PivWeakPin value) weakPin,
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(PivInvalidPin value)? invalidPin,
|
||||||
|
TResult? Function(PivWeakPin value)? weakPin,
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(PivInvalidPin value)? invalidPin,
|
||||||
|
TResult Function(PivWeakPin value)? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $PivPinFailureReasonCopyWith<$Res> {
|
||||||
|
factory $PivPinFailureReasonCopyWith(
|
||||||
|
PivPinFailureReason value, $Res Function(PivPinFailureReason) then) =
|
||||||
|
_$PivPinFailureReasonCopyWithImpl<$Res, PivPinFailureReason>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$PivPinFailureReasonCopyWithImpl<$Res, $Val extends PivPinFailureReason>
|
||||||
|
implements $PivPinFailureReasonCopyWith<$Res> {
|
||||||
|
_$PivPinFailureReasonCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$PivInvalidPinImplCopyWith<$Res> {
|
||||||
|
factory _$$PivInvalidPinImplCopyWith(
|
||||||
|
_$PivInvalidPinImpl value, $Res Function(_$PivInvalidPinImpl) then) =
|
||||||
|
__$$PivInvalidPinImplCopyWithImpl<$Res>;
|
||||||
|
@useResult
|
||||||
|
$Res call({int attemptsRemaining});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$PivInvalidPinImplCopyWithImpl<$Res>
|
||||||
|
extends _$PivPinFailureReasonCopyWithImpl<$Res, _$PivInvalidPinImpl>
|
||||||
|
implements _$$PivInvalidPinImplCopyWith<$Res> {
|
||||||
|
__$$PivInvalidPinImplCopyWithImpl(
|
||||||
|
_$PivInvalidPinImpl _value, $Res Function(_$PivInvalidPinImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? attemptsRemaining = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$PivInvalidPinImpl(
|
||||||
|
null == attemptsRemaining
|
||||||
|
? _value.attemptsRemaining
|
||||||
|
: attemptsRemaining // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$PivInvalidPinImpl implements PivInvalidPin {
|
||||||
|
_$PivInvalidPinImpl(this.attemptsRemaining);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final int attemptsRemaining;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'PivPinFailureReason.invalidPin(attemptsRemaining: $attemptsRemaining)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$PivInvalidPinImpl &&
|
||||||
|
(identical(other.attemptsRemaining, attemptsRemaining) ||
|
||||||
|
other.attemptsRemaining == attemptsRemaining));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, attemptsRemaining);
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$PivInvalidPinImplCopyWith<_$PivInvalidPinImpl> get copyWith =>
|
||||||
|
__$$PivInvalidPinImplCopyWithImpl<_$PivInvalidPinImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(int attemptsRemaining) invalidPin,
|
||||||
|
required TResult Function() weakPin,
|
||||||
|
}) {
|
||||||
|
return invalidPin(attemptsRemaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(int attemptsRemaining)? invalidPin,
|
||||||
|
TResult? Function()? weakPin,
|
||||||
|
}) {
|
||||||
|
return invalidPin?.call(attemptsRemaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(int attemptsRemaining)? invalidPin,
|
||||||
|
TResult Function()? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (invalidPin != null) {
|
||||||
|
return invalidPin(attemptsRemaining);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(PivInvalidPin value) invalidPin,
|
||||||
|
required TResult Function(PivWeakPin value) weakPin,
|
||||||
|
}) {
|
||||||
|
return invalidPin(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(PivInvalidPin value)? invalidPin,
|
||||||
|
TResult? Function(PivWeakPin value)? weakPin,
|
||||||
|
}) {
|
||||||
|
return invalidPin?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(PivInvalidPin value)? invalidPin,
|
||||||
|
TResult Function(PivWeakPin value)? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (invalidPin != null) {
|
||||||
|
return invalidPin(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PivInvalidPin implements PivPinFailureReason {
|
||||||
|
factory PivInvalidPin(final int attemptsRemaining) = _$PivInvalidPinImpl;
|
||||||
|
|
||||||
|
int get attemptsRemaining;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
_$$PivInvalidPinImplCopyWith<_$PivInvalidPinImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$PivWeakPinImplCopyWith<$Res> {
|
||||||
|
factory _$$PivWeakPinImplCopyWith(
|
||||||
|
_$PivWeakPinImpl value, $Res Function(_$PivWeakPinImpl) then) =
|
||||||
|
__$$PivWeakPinImplCopyWithImpl<$Res>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$PivWeakPinImplCopyWithImpl<$Res>
|
||||||
|
extends _$PivPinFailureReasonCopyWithImpl<$Res, _$PivWeakPinImpl>
|
||||||
|
implements _$$PivWeakPinImplCopyWith<$Res> {
|
||||||
|
__$$PivWeakPinImplCopyWithImpl(
|
||||||
|
_$PivWeakPinImpl _value, $Res Function(_$PivWeakPinImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$PivWeakPinImpl implements PivWeakPin {
|
||||||
|
const _$PivWeakPinImpl();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'PivPinFailureReason.weakPin()';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType && other is _$PivWeakPinImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(int attemptsRemaining) invalidPin,
|
||||||
|
required TResult Function() weakPin,
|
||||||
|
}) {
|
||||||
|
return weakPin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(int attemptsRemaining)? invalidPin,
|
||||||
|
TResult? Function()? weakPin,
|
||||||
|
}) {
|
||||||
|
return weakPin?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(int attemptsRemaining)? invalidPin,
|
||||||
|
TResult Function()? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (weakPin != null) {
|
||||||
|
return weakPin();
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(PivInvalidPin value) invalidPin,
|
||||||
|
required TResult Function(PivWeakPin value) weakPin,
|
||||||
|
}) {
|
||||||
|
return weakPin(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(PivInvalidPin value)? invalidPin,
|
||||||
|
TResult? Function(PivWeakPin value)? weakPin,
|
||||||
|
}) {
|
||||||
|
return weakPin?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(PivInvalidPin value)? invalidPin,
|
||||||
|
TResult Function(PivWeakPin value)? weakPin,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (weakPin != null) {
|
||||||
|
return weakPin(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PivWeakPin implements PivPinFailureReason {
|
||||||
|
const factory PivWeakPin() = _$PivWeakPinImpl;
|
||||||
|
}
|
||||||
|
|
||||||
ManagementKeyMetadata _$ManagementKeyMetadataFromJson(
|
ManagementKeyMetadata _$ManagementKeyMetadataFromJson(
|
||||||
Map<String, dynamic> json) {
|
Map<String, dynamic> json) {
|
||||||
return _ManagementKeyMetadata.fromJson(json);
|
return _ManagementKeyMetadata.fromJson(json);
|
||||||
|
@ -106,14 +106,19 @@ class _ManageKeyDialogState extends ConsumerState<ManageKeyDialog> {
|
|||||||
if (_usesStoredKey) {
|
if (_usesStoredKey) {
|
||||||
final status = (await notifier.verifyPin(_currentController.text)).when(
|
final status = (await notifier.verifyPin(_currentController.text)).when(
|
||||||
success: () => true,
|
success: () => true,
|
||||||
failure: (attemptsRemaining) {
|
failure: (reason) {
|
||||||
_currentController.selection = TextSelection(
|
reason.maybeWhen(
|
||||||
baseOffset: 0, extentOffset: _currentController.text.length);
|
invalidPin: (attemptsRemaining) {
|
||||||
_currentFocus.requestFocus();
|
_currentController.selection = TextSelection(
|
||||||
setState(() {
|
baseOffset: 0, extentOffset: _currentController.text.length);
|
||||||
_attemptsRemaining = attemptsRemaining;
|
_currentFocus.requestFocus();
|
||||||
_currentIsWrong = true;
|
setState(() {
|
||||||
});
|
_attemptsRemaining = attemptsRemaining;
|
||||||
|
_currentIsWrong = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
orElse: () {},
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -21,6 +21,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
|||||||
|
|
||||||
import '../../app/message.dart';
|
import '../../app/message.dart';
|
||||||
import '../../app/models.dart';
|
import '../../app/models.dart';
|
||||||
|
import '../../app/state.dart';
|
||||||
import '../../widgets/app_input_decoration.dart';
|
import '../../widgets/app_input_decoration.dart';
|
||||||
import '../../widgets/app_text_field.dart';
|
import '../../widgets/app_text_field.dart';
|
||||||
import '../../widgets/responsive_dialog.dart';
|
import '../../widgets/responsive_dialog.dart';
|
||||||
@ -46,10 +47,13 @@ class ManagePinPukDialog extends ConsumerStatefulWidget {
|
|||||||
class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
||||||
final _currentPinController = TextEditingController();
|
final _currentPinController = TextEditingController();
|
||||||
final _currentPinFocus = FocusNode();
|
final _currentPinFocus = FocusNode();
|
||||||
String _newPin = '';
|
final _newPinController = TextEditingController();
|
||||||
|
final _newPinFocus = FocusNode();
|
||||||
String _confirmPin = '';
|
String _confirmPin = '';
|
||||||
bool _pinIsBlocked = false;
|
bool _pinIsBlocked = false;
|
||||||
bool _currentIsWrong = false;
|
bool _currentIsWrong = false;
|
||||||
|
bool _newIsWrong = false;
|
||||||
|
String? _newPinError;
|
||||||
int _attemptsRemaining = -1;
|
int _attemptsRemaining = -1;
|
||||||
bool _isObscureCurrent = true;
|
bool _isObscureCurrent = true;
|
||||||
bool _isObscureNew = true;
|
bool _isObscureNew = true;
|
||||||
@ -80,23 +84,26 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
|||||||
void dispose() {
|
void dispose() {
|
||||||
_currentPinController.dispose();
|
_currentPinController.dispose();
|
||||||
_currentPinFocus.dispose();
|
_currentPinFocus.dispose();
|
||||||
|
_newPinController.dispose();
|
||||||
|
_newPinFocus.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
_submit() async {
|
_submit() async {
|
||||||
final notifier = ref.read(pivStateProvider(widget.path).notifier);
|
final notifier = ref.read(pivStateProvider(widget.path).notifier);
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
|
||||||
final result = await switch (widget.target) {
|
final result = await switch (widget.target) {
|
||||||
ManageTarget.pin =>
|
ManageTarget.pin =>
|
||||||
notifier.changePin(_currentPinController.text, _newPin),
|
notifier.changePin(_currentPinController.text, _newPinController.text),
|
||||||
ManageTarget.puk =>
|
ManageTarget.puk =>
|
||||||
notifier.changePuk(_currentPinController.text, _newPin),
|
notifier.changePuk(_currentPinController.text, _newPinController.text),
|
||||||
ManageTarget.unblock =>
|
ManageTarget.unblock =>
|
||||||
notifier.unblockPin(_currentPinController.text, _newPin),
|
notifier.unblockPin(_currentPinController.text, _newPinController.text),
|
||||||
};
|
};
|
||||||
|
|
||||||
result.when(success: () {
|
result.when(success: () {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
final l10n = AppLocalizations.of(context)!;
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
showMessage(
|
showMessage(
|
||||||
context,
|
context,
|
||||||
@ -104,17 +111,31 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
|||||||
ManageTarget.puk => l10n.s_puk_set,
|
ManageTarget.puk => l10n.s_puk_set,
|
||||||
_ => l10n.s_pin_set,
|
_ => l10n.s_pin_set,
|
||||||
});
|
});
|
||||||
}, failure: (attemptsRemaining) {
|
}, failure: (reason) {
|
||||||
_currentPinController.selection = TextSelection(
|
reason.when(
|
||||||
baseOffset: 0, extentOffset: _currentPinController.text.length);
|
invalidPin: (attemptsRemaining) {
|
||||||
_currentPinFocus.requestFocus();
|
_currentPinController.selection = TextSelection(
|
||||||
setState(() {
|
baseOffset: 0, extentOffset: _currentPinController.text.length);
|
||||||
_attemptsRemaining = attemptsRemaining;
|
_currentPinFocus.requestFocus();
|
||||||
_currentIsWrong = true;
|
setState(() {
|
||||||
if (_attemptsRemaining == 0) {
|
_attemptsRemaining = attemptsRemaining;
|
||||||
_pinIsBlocked = true;
|
_currentIsWrong = true;
|
||||||
}
|
if (_attemptsRemaining == 0) {
|
||||||
});
|
_pinIsBlocked = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
weakPin: () {
|
||||||
|
_newPinController.selection = TextSelection(
|
||||||
|
baseOffset: 0, extentOffset: _newPinController.text.length);
|
||||||
|
_newPinFocus.requestFocus();
|
||||||
|
setState(() {
|
||||||
|
_newPinError = l10n.p_pin_puk_complexity_failure(
|
||||||
|
widget.target == ManageTarget.puk ? l10n.s_puk : l10n.s_pin);
|
||||||
|
_newIsWrong = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,10 +144,11 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
|||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
final currentPin = _currentPinController.text;
|
final currentPin = _currentPinController.text;
|
||||||
final currentPinLen = byteLength(currentPin);
|
final currentPinLen = byteLength(currentPin);
|
||||||
final newPinLen = byteLength(_newPin);
|
final newPin = _newPinController.text;
|
||||||
|
final newPinLen = byteLength(newPin);
|
||||||
final isValid = !_currentIsWrong &&
|
final isValid = !_currentIsWrong &&
|
||||||
_newPin.isNotEmpty &&
|
newPin.isNotEmpty &&
|
||||||
_newPin == _confirmPin &&
|
newPin == _confirmPin &&
|
||||||
currentPin.isNotEmpty;
|
currentPin.isNotEmpty;
|
||||||
|
|
||||||
final titleText = switch (widget.target) {
|
final titleText = switch (widget.target) {
|
||||||
@ -140,6 +162,10 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
|||||||
final showDefaultPukUsed =
|
final showDefaultPukUsed =
|
||||||
widget.target != ManageTarget.pin && _defaultPukUsed;
|
widget.target != ManageTarget.pin && _defaultPukUsed;
|
||||||
|
|
||||||
|
final hasPinComplexity =
|
||||||
|
ref.read(currentDeviceDataProvider).valueOrNull?.info.pinComplexity ??
|
||||||
|
false;
|
||||||
|
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(titleText),
|
title: Text(titleText),
|
||||||
actions: [
|
actions: [
|
||||||
@ -213,21 +239,29 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
).init(),
|
).init(),
|
||||||
Text(l10n.p_enter_new_piv_pin_puk(
|
Text(hasPinComplexity
|
||||||
widget.target == ManageTarget.puk ? l10n.s_puk : l10n.s_pin)),
|
? l10n.p_enter_new_piv_pin_puk_complexity_active(
|
||||||
|
widget.target == ManageTarget.puk ? l10n.s_puk : l10n.s_pin,
|
||||||
|
'123456')
|
||||||
|
: l10n.p_enter_new_piv_pin_puk(widget.target == ManageTarget.puk
|
||||||
|
? l10n.s_puk
|
||||||
|
: l10n.s_pin)),
|
||||||
AppTextField(
|
AppTextField(
|
||||||
key: keys.newPinPukField,
|
key: keys.newPinPukField,
|
||||||
autofocus: showDefaultPinUsed || showDefaultPukUsed,
|
autofocus: showDefaultPinUsed || showDefaultPukUsed,
|
||||||
obscureText: _isObscureNew,
|
obscureText: _isObscureNew,
|
||||||
|
controller: _newPinController,
|
||||||
|
focusNode: _newPinFocus,
|
||||||
maxLength: 8,
|
maxLength: 8,
|
||||||
inputFormatters: [limitBytesLength(8)],
|
inputFormatters: [limitBytesLength(8)],
|
||||||
buildCounter: buildByteCounterFor(_newPin),
|
buildCounter: buildByteCounterFor(newPin),
|
||||||
autofillHints: const [AutofillHints.newPassword],
|
autofillHints: const [AutofillHints.newPassword],
|
||||||
decoration: AppInputDecoration(
|
decoration: AppInputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: widget.target == ManageTarget.puk
|
labelText: widget.target == ManageTarget.puk
|
||||||
? l10n.s_new_puk
|
? l10n.s_new_puk
|
||||||
: l10n.s_new_pin,
|
: l10n.s_new_pin,
|
||||||
|
errorText: _newIsWrong ? _newPinError : null,
|
||||||
prefixIcon: const Icon(Symbols.password),
|
prefixIcon: const Icon(Symbols.password),
|
||||||
suffixIcon: IconButton(
|
suffixIcon: IconButton(
|
||||||
icon: Icon(_isObscureNew
|
icon: Icon(_isObscureNew
|
||||||
@ -247,7 +281,7 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
|||||||
textInputAction: TextInputAction.next,
|
textInputAction: TextInputAction.next,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_newPin = value;
|
_newIsWrong = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSubmitted: (_) {
|
onSubmitted: (_) {
|
||||||
@ -284,8 +318,9 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
|||||||
),
|
),
|
||||||
enabled: currentPinLen >= _minPinLen && newPinLen >= 6,
|
enabled: currentPinLen >= _minPinLen && newPinLen >= 6,
|
||||||
errorText:
|
errorText:
|
||||||
newPinLen == _confirmPin.length && _newPin != _confirmPin
|
newPinLen == _confirmPin.length && newPin != _confirmPin
|
||||||
? (widget.target == ManageTarget.pin
|
? (widget.target == ManageTarget.pin ||
|
||||||
|
widget.target == ManageTarget.unblock
|
||||||
? l10n.l_pin_mismatch
|
? l10n.l_pin_mismatch
|
||||||
: l10n.l_puk_mismatch)
|
: l10n.l_puk_mismatch)
|
||||||
: null,
|
: null,
|
||||||
|
@ -60,14 +60,19 @@ class _PinDialogState extends ConsumerState<PinDialog> {
|
|||||||
success: () {
|
success: () {
|
||||||
navigator.pop(true);
|
navigator.pop(true);
|
||||||
},
|
},
|
||||||
failure: (attemptsRemaining) {
|
failure: (reason) {
|
||||||
_pinController.selection = TextSelection(
|
reason.maybeWhen(
|
||||||
baseOffset: 0, extentOffset: _pinController.text.length);
|
invalidPin: (attemptsRemaining) {
|
||||||
_pinFocus.requestFocus();
|
_pinController.selection = TextSelection(
|
||||||
setState(() {
|
baseOffset: 0, extentOffset: _pinController.text.length);
|
||||||
_attemptsRemaining = attemptsRemaining;
|
_pinFocus.requestFocus();
|
||||||
_pinIsWrong = true;
|
setState(() {
|
||||||
});
|
_attemptsRemaining = attemptsRemaining;
|
||||||
|
_pinIsWrong = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
orElse: () {},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} on CancellationException catch (_) {
|
} on CancellationException catch (_) {
|
||||||
|
Loading…
Reference in New Issue
Block a user