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,
|
||||
@SerialName("usb_pid")
|
||||
val usbPid: Int?,
|
||||
@SerialName("pin_complexity")
|
||||
val pinComplexity: Boolean,
|
||||
@SerialName("supported_capabilities")
|
||||
val supportedCapabilities: Capabilities
|
||||
val supportedCapabilities: Capabilities,
|
||||
) {
|
||||
constructor(name: String, isNfc: Boolean, usbPid: Int?, deviceInfo: DeviceInfo) : this(
|
||||
config = Config(deviceInfo.config),
|
||||
@ -63,6 +65,7 @@ data class Info(
|
||||
name = name,
|
||||
isNfc = isNfc,
|
||||
usbPid = usbPid,
|
||||
pinComplexity = deviceInfo.pinComplexity,
|
||||
supportedCapabilities = Capabilities(
|
||||
nfc = deviceInfo.capabilitiesFor(Transport.NFC),
|
||||
usb = deviceInfo.capabilitiesFor(Transport.USB),
|
||||
|
@ -18,5 +18,6 @@ val UnknownDevice = Info(
|
||||
name = "Unrecognized device",
|
||||
isNfc = false,
|
||||
usbPid = null,
|
||||
pinComplexity = false,
|
||||
supportedCapabilities = Capabilities()
|
||||
)
|
@ -313,18 +313,28 @@ class FidoManager(
|
||||
} catch (ctapException: CtapException) {
|
||||
if (ctapException.ctapError == CtapException.ERR_PIN_INVALID ||
|
||||
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)
|
||||
fidoViewModel.updateCredentials(emptyList())
|
||||
val pinRetriesResult = clientPin.pinRetries
|
||||
JSONObject(
|
||||
mapOf(
|
||||
"success" to false,
|
||||
"pinRetries" to pinRetriesResult.count,
|
||||
"authBlocked" to (ctapException.ctapError == CtapException.ERR_PIN_AUTH_BLOCKED)
|
||||
)
|
||||
).toString()
|
||||
|
||||
if (ctapException.ctapError == CtapException.ERR_PIN_POLICY_VIOLATION) {
|
||||
JSONObject(
|
||||
mapOf(
|
||||
"success" to false,
|
||||
"pinViolation" to true
|
||||
)
|
||||
).toString()
|
||||
} else {
|
||||
JSONObject(
|
||||
mapOf(
|
||||
"success" to false,
|
||||
"pinRetries" to clientPin.pinRetries.count,
|
||||
"authBlocked" to (ctapException.ctapError == CtapException.ERR_PIN_AUTH_BLOCKED),
|
||||
)
|
||||
).toString()
|
||||
}
|
||||
} else {
|
||||
throw ctapException
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ class SkyHelper(private val compatUtil: CompatUtil) {
|
||||
name = (device.usbDevice.productName ?: "Yubico Security Key"),
|
||||
isNfc = false,
|
||||
usbPid = pid.value,
|
||||
pinComplexity = false,
|
||||
supportedCapabilities = Capabilities(usb = 0)
|
||||
)
|
||||
}
|
||||
|
@ -75,6 +75,11 @@ class AuthRequiredException(RpcException):
|
||||
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):
|
||||
def __init__(self, message):
|
||||
self.message = message
|
||||
|
@ -19,6 +19,7 @@ from .base import (
|
||||
RpcException,
|
||||
TimeoutException,
|
||||
AuthRequiredException,
|
||||
PinComplexityException,
|
||||
)
|
||||
from fido2.ctap import CtapError
|
||||
from fido2.ctap2 import Ctap2, ClientPin
|
||||
@ -76,6 +77,8 @@ def _handle_pin_error(e, client_pin):
|
||||
raise PinValidationException(
|
||||
pin_retries, e.code == CtapError.ERR.PIN_AUTH_BLOCKED
|
||||
)
|
||||
if e.code == CtapError.ERR.PIN_POLICY_VIOLATION:
|
||||
raise PinComplexityException()
|
||||
raise e
|
||||
|
||||
|
||||
|
@ -20,6 +20,7 @@ from .base import (
|
||||
ChildResetException,
|
||||
TimeoutException,
|
||||
AuthRequiredException,
|
||||
PinComplexityException,
|
||||
)
|
||||
from yubikit.core import NotSupportedError, BadResponseError, InvalidPinError
|
||||
from yubikit.core.smartcard import ApduError, SW
|
||||
@ -80,6 +81,15 @@ class GENERATE_TYPE(str, Enum):
|
||||
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):
|
||||
def __init__(self, connection):
|
||||
super().__init__()
|
||||
@ -208,21 +218,30 @@ class PivNode(RpcNode):
|
||||
def change_pin(self, params, event, signal):
|
||||
old_pin = params.pop("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()
|
||||
|
||||
@action
|
||||
def change_puk(self, params, event, signal):
|
||||
old_puk = params.pop("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()
|
||||
|
||||
@action
|
||||
def unblock_pin(self, params, event, signal):
|
||||
puk = params.pop("puk")
|
||||
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()
|
||||
|
||||
@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]]
|
||||
name = "altgraph"
|
||||
@ -717,13 +717,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "yubikey-manager"
|
||||
version = "5.3.0"
|
||||
version = "5.4.0"
|
||||
description = "Tool for managing your YubiKey configuration."
|
||||
optional = false
|
||||
python-versions = ">=3.8,<4.0"
|
||||
python-versions = "<4.0,>=3.8"
|
||||
files = [
|
||||
{file = "yubikey_manager-5.3.0-py3-none-any.whl", hash = "sha256:9a809620f5c910c1047323570095e10b885002f6b0a2e4d8ced7f62d7c2ce628"},
|
||||
{file = "yubikey_manager-5.3.0.tar.gz", hash = "sha256:5492c36a10ce6a5995b8ea1d32cf5bd60db7587201b2aa3e63e0c1da2334b8b6"},
|
||||
{file = "yubikey_manager-5.4.0-py3-none-any.whl", hash = "sha256:d53acb06c4028a833be7a05ca4145833afef1affa67aaab4347bc50ecce37985"},
|
||||
{file = "yubikey_manager-5.4.0.tar.gz", hash = "sha256:53726a186722cd2683b2f5fd781fc0a2861f47ce62ba9d3527960832c8fabec8"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -787,4 +787,4 @@ files = [
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.8"
|
||||
content-hash = "6664f12e752d8b41c996d11e43a8572ed47f7fbfaaf84fa894be725fe2208d80"
|
||||
content-hash = "7543cc0ac90ea4eb701a7f52321d831bfe05c65e0ae896a6107eb7a9540d8543"
|
||||
|
@ -10,7 +10,7 @@ packages = [
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.8"
|
||||
yubikey-manager = "^5.2"
|
||||
yubikey-manager = "^5.4"
|
||||
mss = "^9.0.1"
|
||||
Pillow = "^10.2.0"
|
||||
zxing-cpp = "^2.2.0"
|
||||
|
@ -109,15 +109,18 @@ class _FidoStateNotifier extends FidoStateNotifier {
|
||||
},
|
||||
));
|
||||
if (response['success'] == true) {
|
||||
_log.debug('FIDO pin set/change successful');
|
||||
_log.debug('FIDO PIN set/change successful');
|
||||
return PinResult.success();
|
||||
}
|
||||
|
||||
_log.debug('FIDO pin set/change failed');
|
||||
return PinResult.failed(
|
||||
response['pinRetries'],
|
||||
response['authBlocked'],
|
||||
);
|
||||
if (response['pinViolation'] == true) {
|
||||
_log.debug('FIDO PIN violation');
|
||||
return PinResult.failed(const FidoPinFailureReason.weakPin());
|
||||
}
|
||||
|
||||
_log.debug('FIDO PIN set/change failed');
|
||||
return PinResult.failed(FidoPinFailureReason.invalidPin(
|
||||
response['pinRetries'], response['authBlocked']));
|
||||
} on PlatformException catch (pe) {
|
||||
var decodedException = pe.decode();
|
||||
if (decodedException is CancellationException) {
|
||||
@ -141,10 +144,8 @@ class _FidoStateNotifier extends FidoStateNotifier {
|
||||
}
|
||||
|
||||
_log.debug('FIDO applet unlock failed');
|
||||
return PinResult.failed(
|
||||
response['pinRetries'],
|
||||
response['authBlocked'],
|
||||
);
|
||||
return PinResult.failed(FidoPinFailureReason.invalidPin(
|
||||
response['pinRetries'], response['authBlocked']));
|
||||
} on PlatformException catch (pe) {
|
||||
var decodedException = pe.decode();
|
||||
if (decodedException is! CancellationException) {
|
||||
|
@ -153,7 +153,11 @@ class _DesktopFidoStateNotifier extends FidoStateNotifier {
|
||||
return unlock(newPin);
|
||||
} on RpcError catch (e) {
|
||||
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;
|
||||
}
|
||||
@ -172,7 +176,8 @@ class _DesktopFidoStateNotifier extends FidoStateNotifier {
|
||||
} on RpcError catch (e) {
|
||||
if (e.status == 'pin-validation') {
|
||||
_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;
|
||||
}
|
||||
|
@ -233,7 +233,12 @@ class _DesktopPivStateNotifier extends PivStateNotifier {
|
||||
return const PinVerificationStatus.success();
|
||||
} on RpcError catch (e) {
|
||||
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;
|
||||
} finally {
|
||||
@ -251,7 +256,12 @@ class _DesktopPivStateNotifier extends PivStateNotifier {
|
||||
return const PinVerificationStatus.success();
|
||||
} on RpcError catch (e) {
|
||||
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;
|
||||
} finally {
|
||||
@ -286,7 +296,12 @@ class _DesktopPivStateNotifier extends PivStateNotifier {
|
||||
return const PinVerificationStatus.success();
|
||||
} on RpcError catch (e) {
|
||||
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;
|
||||
} finally {
|
||||
|
@ -52,7 +52,14 @@ class FidoState with _$FidoState {
|
||||
@freezed
|
||||
class PinResult with _$PinResult {
|
||||
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
|
||||
|
@ -184,19 +184,19 @@ mixin _$PinResult {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() success,
|
||||
required TResult Function(int retries, bool authBlocked) failed,
|
||||
required TResult Function(FidoPinFailureReason reason) failed,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function()? success,
|
||||
TResult? Function(int retries, bool authBlocked)? failed,
|
||||
TResult? Function(FidoPinFailureReason reason)? failed,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? success,
|
||||
TResult Function(int retries, bool authBlocked)? failed,
|
||||
TResult Function(FidoPinFailureReason reason)? failed,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@ -277,7 +277,7 @@ class _$PinSuccessImpl implements _PinSuccess {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() success,
|
||||
required TResult Function(int retries, bool authBlocked) failed,
|
||||
required TResult Function(FidoPinFailureReason reason) failed,
|
||||
}) {
|
||||
return success();
|
||||
}
|
||||
@ -286,7 +286,7 @@ class _$PinSuccessImpl implements _PinSuccess {
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function()? success,
|
||||
TResult? Function(int retries, bool authBlocked)? failed,
|
||||
TResult? Function(FidoPinFailureReason reason)? failed,
|
||||
}) {
|
||||
return success?.call();
|
||||
}
|
||||
@ -295,7 +295,7 @@ class _$PinSuccessImpl implements _PinSuccess {
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? success,
|
||||
TResult Function(int retries, bool authBlocked)? failed,
|
||||
TResult Function(FidoPinFailureReason reason)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (success != null) {
|
||||
@ -346,7 +346,9 @@ abstract class _$$PinFailureImplCopyWith<$Res> {
|
||||
_$PinFailureImpl value, $Res Function(_$PinFailureImpl) then) =
|
||||
__$$PinFailureImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({int retries, bool authBlocked});
|
||||
$Res call({FidoPinFailureReason reason});
|
||||
|
||||
$FidoPinFailureReasonCopyWith<$Res> get reason;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -360,35 +362,36 @@ class __$$PinFailureImplCopyWithImpl<$Res>
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? retries = null,
|
||||
Object? authBlocked = null,
|
||||
Object? reason = null,
|
||||
}) {
|
||||
return _then(_$PinFailureImpl(
|
||||
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,
|
||||
null == reason
|
||||
? _value.reason
|
||||
: reason // ignore: cast_nullable_to_non_nullable
|
||||
as FidoPinFailureReason,
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$FidoPinFailureReasonCopyWith<$Res> get reason {
|
||||
return $FidoPinFailureReasonCopyWith<$Res>(_value.reason, (value) {
|
||||
return _then(_value.copyWith(reason: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$PinFailureImpl implements _PinFailure {
|
||||
_$PinFailureImpl(this.retries, this.authBlocked);
|
||||
_$PinFailureImpl(this.reason);
|
||||
|
||||
@override
|
||||
final int retries;
|
||||
@override
|
||||
final bool authBlocked;
|
||||
final FidoPinFailureReason reason;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PinResult.failed(retries: $retries, authBlocked: $authBlocked)';
|
||||
return 'PinResult.failed(reason: $reason)';
|
||||
}
|
||||
|
||||
@override
|
||||
@ -396,13 +399,11 @@ class _$PinFailureImpl implements _PinFailure {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$PinFailureImpl &&
|
||||
(identical(other.retries, retries) || other.retries == retries) &&
|
||||
(identical(other.authBlocked, authBlocked) ||
|
||||
other.authBlocked == authBlocked));
|
||||
(identical(other.reason, reason) || other.reason == reason));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, retries, authBlocked);
|
||||
int get hashCode => Object.hash(runtimeType, reason);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@ -414,29 +415,29 @@ class _$PinFailureImpl implements _PinFailure {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
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
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
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
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? success,
|
||||
TResult Function(int retries, bool authBlocked)? failed,
|
||||
TResult Function(FidoPinFailureReason reason)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (failed != null) {
|
||||
return failed(retries, authBlocked);
|
||||
return failed(reason);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
@ -474,16 +475,322 @@ class _$PinFailureImpl implements _PinFailure {
|
||||
}
|
||||
|
||||
abstract class _PinFailure implements PinResult {
|
||||
factory _PinFailure(final int retries, final bool authBlocked) =
|
||||
_$PinFailureImpl;
|
||||
factory _PinFailure(final FidoPinFailureReason reason) = _$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;
|
||||
bool get authBlocked;
|
||||
@JsonKey(ignore: true)
|
||||
_$$PinFailureImplCopyWith<_$PinFailureImpl> get copyWith =>
|
||||
_$$FidoInvalidPinImplCopyWith<_$FidoInvalidPinImpl> get copyWith =>
|
||||
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) {
|
||||
return _Fingerprint.fromJson(json);
|
||||
}
|
||||
|
@ -48,7 +48,8 @@ class FidoPinDialog extends ConsumerStatefulWidget {
|
||||
class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
||||
final _currentPinController = TextEditingController();
|
||||
final _currentPinFocus = FocusNode();
|
||||
String _newPin = '';
|
||||
final _newPinController = TextEditingController();
|
||||
final _newPinFocus = FocusNode();
|
||||
String _confirmPin = '';
|
||||
String? _currentPinError;
|
||||
String? _newPinError;
|
||||
@ -63,6 +64,8 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
||||
void dispose() {
|
||||
_currentPinController.dispose();
|
||||
_currentPinFocus.dispose();
|
||||
_newPinController.dispose();
|
||||
_newPinFocus.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@ -77,8 +80,13 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
||||
: (widget.state.forcePinChange ? 4 : widget.state.minPinLength);
|
||||
final currentPinLenOk =
|
||||
_currentPinController.text.length >= currentMinPinLen;
|
||||
final newPinLenOk = _newPin.length >= minPinLength;
|
||||
final isValid = currentPinLenOk && newPinLenOk && _newPin == _confirmPin;
|
||||
final newPinLenOk = _newPinController.text.length >= minPinLength;
|
||||
final isValid =
|
||||
currentPinLenOk && newPinLenOk && _newPinController.text == _confirmPin;
|
||||
|
||||
final hasPinComplexity =
|
||||
ref.read(currentDeviceDataProvider).valueOrNull?.info.pinComplexity ??
|
||||
false;
|
||||
|
||||
return ResponsiveDialog(
|
||||
title: Text(hasPin ? l10n.s_change_pin : l10n.s_set_pin),
|
||||
@ -130,11 +138,15 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
||||
},
|
||||
).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
|
||||
AppTextFormField(
|
||||
key: newPin,
|
||||
initialValue: _newPin,
|
||||
controller: _newPinController,
|
||||
focusNode: _newPinFocus,
|
||||
autofocus: !hasPin,
|
||||
obscureText: _isObscureNew,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
@ -160,7 +172,6 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_newIsWrong = false;
|
||||
_newPin = value;
|
||||
});
|
||||
},
|
||||
).init(),
|
||||
@ -186,10 +197,11 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
||||
_isObscureConfirm ? l10n.s_show_pin : l10n.s_hide_pin,
|
||||
),
|
||||
enabled: !_isBlocked && currentPinLenOk && newPinLenOk,
|
||||
errorText: _newPin.length == _confirmPin.length &&
|
||||
_newPin != _confirmPin
|
||||
? l10n.l_pin_mismatch
|
||||
: null,
|
||||
errorText:
|
||||
_newPinController.text.length == _confirmPin.length &&
|
||||
_newPinController.text != _confirmPin
|
||||
? l10n.l_pin_mismatch
|
||||
: null,
|
||||
helperText: '', // Prevents resizing when errorText shown
|
||||
),
|
||||
onChanged: (value) {
|
||||
@ -219,28 +231,47 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
||||
final oldPin = _currentPinController.text.isNotEmpty
|
||||
? _currentPinController.text
|
||||
: null;
|
||||
final newPin = _newPinController.text;
|
||||
try {
|
||||
final result = await ref
|
||||
.read(fidoStateProvider(widget.devicePath).notifier)
|
||||
.setPin(_newPin, oldPin: oldPin);
|
||||
result.when(success: () {
|
||||
Navigator.of(context).pop(true);
|
||||
showMessage(context, l10n.s_pin_set);
|
||||
}, failed: (retries, authBlocked) {
|
||||
setState(() {
|
||||
_currentPinController.selection = TextSelection(
|
||||
baseOffset: 0, extentOffset: _currentPinController.text.length);
|
||||
_currentPinFocus.requestFocus();
|
||||
if (authBlocked) {
|
||||
_currentPinError = l10n.l_pin_soft_locked;
|
||||
_currentIsWrong = true;
|
||||
_isBlocked = true;
|
||||
} else {
|
||||
_currentPinError = l10n.l_wrong_pin_attempts_remaining(retries);
|
||||
_currentIsWrong = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
.setPin(newPin, oldPin: oldPin);
|
||||
result.whenOrNull(
|
||||
success: () {
|
||||
Navigator.of(context).pop(true);
|
||||
showMessage(context, l10n.s_pin_set);
|
||||
},
|
||||
failed: (reason) {
|
||||
reason.when(
|
||||
invalidPin: (retries, authBlocked) {
|
||||
_currentPinController.selection = TextSelection(
|
||||
baseOffset: 0,
|
||||
extentOffset: _currentPinController.text.length);
|
||||
_currentPinFocus.requestFocus();
|
||||
setState(() {
|
||||
if (authBlocked) {
|
||||
_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 (_) {
|
||||
// ignored
|
||||
} catch (e) {
|
||||
|
@ -60,15 +60,20 @@ class _PinEntryFormState extends ConsumerState<PinEntryForm> {
|
||||
final result = await ref
|
||||
.read(fidoStateProvider(widget._deviceNode.path).notifier)
|
||||
.unlock(_pinController.text);
|
||||
result.whenOrNull(failed: (retries, authBlocked) {
|
||||
_pinController.selection = TextSelection(
|
||||
baseOffset: 0, extentOffset: _pinController.text.length);
|
||||
_pinFocus.requestFocus();
|
||||
setState(() {
|
||||
_pinIsWrong = true;
|
||||
_retries = retries;
|
||||
_blocked = authBlocked;
|
||||
});
|
||||
result.whenOrNull(failed: (reason) {
|
||||
reason.maybeWhen(
|
||||
invalidPin: (retries, authBlocked) {
|
||||
_pinController.selection = TextSelection(
|
||||
baseOffset: 0, extentOffset: _pinController.text.length);
|
||||
_pinFocus.requestFocus();
|
||||
setState(() {
|
||||
_pinIsWrong = true;
|
||||
_retries = retries;
|
||||
_blocked = authBlocked;
|
||||
});
|
||||
},
|
||||
orElse: () {},
|
||||
);
|
||||
});
|
||||
} on CancellationException catch (_) {
|
||||
// ignored
|
||||
|
@ -252,6 +252,18 @@
|
||||
"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": {
|
||||
"placeholders": {
|
||||
@ -288,6 +300,14 @@
|
||||
"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,
|
||||
"p_pin_required_desc": null,
|
||||
"l_piv_pin_blocked": null,
|
||||
@ -298,6 +318,19 @@
|
||||
"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_puk": null,
|
||||
"l_default_pin_used": null,
|
||||
|
@ -252,6 +252,18 @@
|
||||
"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": {
|
||||
"placeholders": {
|
||||
@ -288,6 +300,14 @@
|
||||
"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",
|
||||
"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",
|
||||
@ -298,6 +318,19 @@
|
||||
"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_puk": "Warning: Default PUK used",
|
||||
"l_default_pin_used": "Default PIN used",
|
||||
|
@ -252,6 +252,18 @@
|
||||
"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": {
|
||||
"placeholders": {
|
||||
@ -288,6 +300,14 @@
|
||||
"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",
|
||||
"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",
|
||||
@ -298,6 +318,19 @@
|
||||
"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_puk": null,
|
||||
"l_default_pin_used": null,
|
||||
|
@ -252,6 +252,18 @@
|
||||
"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": {
|
||||
"placeholders": {
|
||||
@ -288,6 +300,14 @@
|
||||
"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が必要",
|
||||
"p_pin_required_desc": "実行しようとしている操作には、PIV PINの入力が必要です",
|
||||
"l_piv_pin_blocked": "ブロックされています。PUK を使用してリセットしてください",
|
||||
@ -298,6 +318,19 @@
|
||||
"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_puk": null,
|
||||
"l_default_pin_used": null,
|
||||
|
@ -252,6 +252,18 @@
|
||||
"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": {
|
||||
"placeholders": {
|
||||
@ -288,6 +300,14 @@
|
||||
"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",
|
||||
"p_pin_required_desc": "Czynność, którą zamierzasz wykonać, wymaga wprowadzenia kodu PIN PIV.",
|
||||
"l_piv_pin_blocked": "Zablokowano, użyj PUK, aby zresetować",
|
||||
@ -298,6 +318,19 @@
|
||||
"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_puk": null,
|
||||
"l_default_pin_used": null,
|
||||
|
@ -86,7 +86,8 @@ class DeviceInfo with _$DeviceInfo {
|
||||
Map<Transport, int> supportedCapabilities,
|
||||
bool isLocked,
|
||||
bool isFips,
|
||||
bool isSky) = _DeviceInfo;
|
||||
bool isSky,
|
||||
bool pinComplexity) = _DeviceInfo;
|
||||
|
||||
factory DeviceInfo.fromJson(Map<String, dynamic> json) =>
|
||||
_$DeviceInfoFromJson(json);
|
||||
|
@ -245,6 +245,7 @@ mixin _$DeviceInfo {
|
||||
bool get isLocked => throw _privateConstructorUsedError;
|
||||
bool get isFips => throw _privateConstructorUsedError;
|
||||
bool get isSky => throw _privateConstructorUsedError;
|
||||
bool get pinComplexity => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
@ -266,7 +267,8 @@ abstract class $DeviceInfoCopyWith<$Res> {
|
||||
Map<Transport, int> supportedCapabilities,
|
||||
bool isLocked,
|
||||
bool isFips,
|
||||
bool isSky});
|
||||
bool isSky,
|
||||
bool pinComplexity});
|
||||
|
||||
$DeviceConfigCopyWith<$Res> get config;
|
||||
$VersionCopyWith<$Res> get version;
|
||||
@ -293,6 +295,7 @@ class _$DeviceInfoCopyWithImpl<$Res, $Val extends DeviceInfo>
|
||||
Object? isLocked = null,
|
||||
Object? isFips = null,
|
||||
Object? isSky = null,
|
||||
Object? pinComplexity = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
config: null == config
|
||||
@ -327,6 +330,10 @@ class _$DeviceInfoCopyWithImpl<$Res, $Val extends DeviceInfo>
|
||||
? _value.isSky
|
||||
: isSky // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
pinComplexity: null == pinComplexity
|
||||
? _value.pinComplexity
|
||||
: pinComplexity // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
@ -363,7 +370,8 @@ abstract class _$$DeviceInfoImplCopyWith<$Res>
|
||||
Map<Transport, int> supportedCapabilities,
|
||||
bool isLocked,
|
||||
bool isFips,
|
||||
bool isSky});
|
||||
bool isSky,
|
||||
bool pinComplexity});
|
||||
|
||||
@override
|
||||
$DeviceConfigCopyWith<$Res> get config;
|
||||
@ -390,6 +398,7 @@ class __$$DeviceInfoImplCopyWithImpl<$Res>
|
||||
Object? isLocked = null,
|
||||
Object? isFips = null,
|
||||
Object? isSky = null,
|
||||
Object? pinComplexity = null,
|
||||
}) {
|
||||
return _then(_$DeviceInfoImpl(
|
||||
null == config
|
||||
@ -424,6 +433,10 @@ class __$$DeviceInfoImplCopyWithImpl<$Res>
|
||||
? _value.isSky
|
||||
: isSky // ignore: cast_nullable_to_non_nullable
|
||||
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,
|
||||
this.isLocked,
|
||||
this.isFips,
|
||||
this.isSky)
|
||||
this.isSky,
|
||||
this.pinComplexity)
|
||||
: _supportedCapabilities = supportedCapabilities;
|
||||
|
||||
factory _$DeviceInfoImpl.fromJson(Map<String, dynamic> json) =>
|
||||
@ -468,10 +482,12 @@ class _$DeviceInfoImpl implements _DeviceInfo {
|
||||
final bool isFips;
|
||||
@override
|
||||
final bool isSky;
|
||||
@override
|
||||
final bool pinComplexity;
|
||||
|
||||
@override
|
||||
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
|
||||
@ -489,7 +505,9 @@ class _$DeviceInfoImpl implements _DeviceInfo {
|
||||
(identical(other.isLocked, isLocked) ||
|
||||
other.isLocked == isLocked) &&
|
||||
(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)
|
||||
@ -503,7 +521,8 @@ class _$DeviceInfoImpl implements _DeviceInfo {
|
||||
const DeepCollectionEquality().hash(_supportedCapabilities),
|
||||
isLocked,
|
||||
isFips,
|
||||
isSky);
|
||||
isSky,
|
||||
pinComplexity);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@ -528,7 +547,8 @@ abstract class _DeviceInfo implements DeviceInfo {
|
||||
final Map<Transport, int> supportedCapabilities,
|
||||
final bool isLocked,
|
||||
final bool isFips,
|
||||
final bool isSky) = _$DeviceInfoImpl;
|
||||
final bool isSky,
|
||||
final bool pinComplexity) = _$DeviceInfoImpl;
|
||||
|
||||
factory _DeviceInfo.fromJson(Map<String, dynamic> json) =
|
||||
_$DeviceInfoImpl.fromJson;
|
||||
@ -550,6 +570,8 @@ abstract class _DeviceInfo implements DeviceInfo {
|
||||
@override
|
||||
bool get isSky;
|
||||
@override
|
||||
bool get pinComplexity;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$DeviceInfoImplCopyWith<_$DeviceInfoImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
@ -42,6 +42,7 @@ _$DeviceInfoImpl _$$DeviceInfoImplFromJson(Map<String, dynamic> json) =>
|
||||
json['is_locked'] as bool,
|
||||
json['is_fips'] as bool,
|
||||
json['is_sky'] as bool,
|
||||
json['pin_complexity'] as bool,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DeviceInfoImplToJson(_$DeviceInfoImpl instance) =>
|
||||
@ -55,6 +56,7 @@ Map<String, dynamic> _$$DeviceInfoImplToJson(_$DeviceInfoImpl instance) =>
|
||||
'is_locked': instance.isLocked,
|
||||
'is_fips': instance.isFips,
|
||||
'is_sky': instance.isSky,
|
||||
'pin_complexity': instance.pinComplexity,
|
||||
};
|
||||
|
||||
const _$FormFactorEnumMap = {
|
||||
|
@ -209,7 +209,14 @@ class PinMetadata with _$PinMetadata {
|
||||
@freezed
|
||||
class PinVerificationStatus with _$PinVerificationStatus {
|
||||
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
|
||||
|
@ -193,19 +193,19 @@ mixin _$PinVerificationStatus {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() success,
|
||||
required TResult Function(int attemptsRemaining) failure,
|
||||
required TResult Function(PivPinFailureReason reason) failure,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function()? success,
|
||||
TResult? Function(int attemptsRemaining)? failure,
|
||||
TResult? Function(PivPinFailureReason reason)? failure,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? success,
|
||||
TResult Function(int attemptsRemaining)? failure,
|
||||
TResult Function(PivPinFailureReason reason)? failure,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@ -288,7 +288,7 @@ class _$PinSuccessImpl implements PinSuccess {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() success,
|
||||
required TResult Function(int attemptsRemaining) failure,
|
||||
required TResult Function(PivPinFailureReason reason) failure,
|
||||
}) {
|
||||
return success();
|
||||
}
|
||||
@ -297,7 +297,7 @@ class _$PinSuccessImpl implements PinSuccess {
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function()? success,
|
||||
TResult? Function(int attemptsRemaining)? failure,
|
||||
TResult? Function(PivPinFailureReason reason)? failure,
|
||||
}) {
|
||||
return success?.call();
|
||||
}
|
||||
@ -306,7 +306,7 @@ class _$PinSuccessImpl implements PinSuccess {
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? success,
|
||||
TResult Function(int attemptsRemaining)? failure,
|
||||
TResult Function(PivPinFailureReason reason)? failure,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (success != null) {
|
||||
@ -357,7 +357,9 @@ abstract class _$$PinFailureImplCopyWith<$Res> {
|
||||
_$PinFailureImpl value, $Res Function(_$PinFailureImpl) then) =
|
||||
__$$PinFailureImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({int attemptsRemaining});
|
||||
$Res call({PivPinFailureReason reason});
|
||||
|
||||
$PivPinFailureReasonCopyWith<$Res> get reason;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -371,28 +373,36 @@ class __$$PinFailureImplCopyWithImpl<$Res>
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? attemptsRemaining = null,
|
||||
Object? reason = null,
|
||||
}) {
|
||||
return _then(_$PinFailureImpl(
|
||||
null == attemptsRemaining
|
||||
? _value.attemptsRemaining
|
||||
: attemptsRemaining // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
null == reason
|
||||
? _value.reason
|
||||
: reason // ignore: cast_nullable_to_non_nullable
|
||||
as PivPinFailureReason,
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$PivPinFailureReasonCopyWith<$Res> get reason {
|
||||
return $PivPinFailureReasonCopyWith<$Res>(_value.reason, (value) {
|
||||
return _then(_value.copyWith(reason: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$PinFailureImpl implements PinFailure {
|
||||
_$PinFailureImpl(this.attemptsRemaining);
|
||||
_$PinFailureImpl(this.reason);
|
||||
|
||||
@override
|
||||
final int attemptsRemaining;
|
||||
final PivPinFailureReason reason;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PinVerificationStatus.failure(attemptsRemaining: $attemptsRemaining)';
|
||||
return 'PinVerificationStatus.failure(reason: $reason)';
|
||||
}
|
||||
|
||||
@override
|
||||
@ -400,12 +410,11 @@ class _$PinFailureImpl implements PinFailure {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$PinFailureImpl &&
|
||||
(identical(other.attemptsRemaining, attemptsRemaining) ||
|
||||
other.attemptsRemaining == attemptsRemaining));
|
||||
(identical(other.reason, reason) || other.reason == reason));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, attemptsRemaining);
|
||||
int get hashCode => Object.hash(runtimeType, reason);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@ -417,29 +426,29 @@ class _$PinFailureImpl implements PinFailure {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() success,
|
||||
required TResult Function(int attemptsRemaining) failure,
|
||||
required TResult Function(PivPinFailureReason reason) failure,
|
||||
}) {
|
||||
return failure(attemptsRemaining);
|
||||
return failure(reason);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function()? success,
|
||||
TResult? Function(int attemptsRemaining)? failure,
|
||||
TResult? Function(PivPinFailureReason reason)? failure,
|
||||
}) {
|
||||
return failure?.call(attemptsRemaining);
|
||||
return failure?.call(reason);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? success,
|
||||
TResult Function(int attemptsRemaining)? failure,
|
||||
TResult Function(PivPinFailureReason reason)? failure,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (failure != null) {
|
||||
return failure(attemptsRemaining);
|
||||
return failure(reason);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
@ -477,14 +486,310 @@ class _$PinFailureImpl implements PinFailure {
|
||||
}
|
||||
|
||||
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)
|
||||
_$$PinFailureImplCopyWith<_$PinFailureImpl> get copyWith =>
|
||||
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(
|
||||
Map<String, dynamic> json) {
|
||||
return _ManagementKeyMetadata.fromJson(json);
|
||||
|
@ -106,14 +106,19 @@ class _ManageKeyDialogState extends ConsumerState<ManageKeyDialog> {
|
||||
if (_usesStoredKey) {
|
||||
final status = (await notifier.verifyPin(_currentController.text)).when(
|
||||
success: () => true,
|
||||
failure: (attemptsRemaining) {
|
||||
_currentController.selection = TextSelection(
|
||||
baseOffset: 0, extentOffset: _currentController.text.length);
|
||||
_currentFocus.requestFocus();
|
||||
setState(() {
|
||||
_attemptsRemaining = attemptsRemaining;
|
||||
_currentIsWrong = true;
|
||||
});
|
||||
failure: (reason) {
|
||||
reason.maybeWhen(
|
||||
invalidPin: (attemptsRemaining) {
|
||||
_currentController.selection = TextSelection(
|
||||
baseOffset: 0, extentOffset: _currentController.text.length);
|
||||
_currentFocus.requestFocus();
|
||||
setState(() {
|
||||
_attemptsRemaining = attemptsRemaining;
|
||||
_currentIsWrong = true;
|
||||
});
|
||||
},
|
||||
orElse: () {},
|
||||
);
|
||||
return false;
|
||||
},
|
||||
);
|
||||
|
@ -21,6 +21,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
import '../../app/message.dart';
|
||||
import '../../app/models.dart';
|
||||
import '../../app/state.dart';
|
||||
import '../../widgets/app_input_decoration.dart';
|
||||
import '../../widgets/app_text_field.dart';
|
||||
import '../../widgets/responsive_dialog.dart';
|
||||
@ -46,10 +47,13 @@ class ManagePinPukDialog extends ConsumerStatefulWidget {
|
||||
class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
||||
final _currentPinController = TextEditingController();
|
||||
final _currentPinFocus = FocusNode();
|
||||
String _newPin = '';
|
||||
final _newPinController = TextEditingController();
|
||||
final _newPinFocus = FocusNode();
|
||||
String _confirmPin = '';
|
||||
bool _pinIsBlocked = false;
|
||||
bool _currentIsWrong = false;
|
||||
bool _newIsWrong = false;
|
||||
String? _newPinError;
|
||||
int _attemptsRemaining = -1;
|
||||
bool _isObscureCurrent = true;
|
||||
bool _isObscureNew = true;
|
||||
@ -80,23 +84,26 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
||||
void dispose() {
|
||||
_currentPinController.dispose();
|
||||
_currentPinFocus.dispose();
|
||||
_newPinController.dispose();
|
||||
_newPinFocus.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
_submit() async {
|
||||
final notifier = ref.read(pivStateProvider(widget.path).notifier);
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
|
||||
final result = await switch (widget.target) {
|
||||
ManageTarget.pin =>
|
||||
notifier.changePin(_currentPinController.text, _newPin),
|
||||
notifier.changePin(_currentPinController.text, _newPinController.text),
|
||||
ManageTarget.puk =>
|
||||
notifier.changePuk(_currentPinController.text, _newPin),
|
||||
notifier.changePuk(_currentPinController.text, _newPinController.text),
|
||||
ManageTarget.unblock =>
|
||||
notifier.unblockPin(_currentPinController.text, _newPin),
|
||||
notifier.unblockPin(_currentPinController.text, _newPinController.text),
|
||||
};
|
||||
|
||||
result.when(success: () {
|
||||
if (!mounted) return;
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
Navigator.of(context).pop();
|
||||
showMessage(
|
||||
context,
|
||||
@ -104,17 +111,31 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
||||
ManageTarget.puk => l10n.s_puk_set,
|
||||
_ => l10n.s_pin_set,
|
||||
});
|
||||
}, failure: (attemptsRemaining) {
|
||||
_currentPinController.selection = TextSelection(
|
||||
baseOffset: 0, extentOffset: _currentPinController.text.length);
|
||||
_currentPinFocus.requestFocus();
|
||||
setState(() {
|
||||
_attemptsRemaining = attemptsRemaining;
|
||||
_currentIsWrong = true;
|
||||
if (_attemptsRemaining == 0) {
|
||||
_pinIsBlocked = true;
|
||||
}
|
||||
});
|
||||
}, failure: (reason) {
|
||||
reason.when(
|
||||
invalidPin: (attemptsRemaining) {
|
||||
_currentPinController.selection = TextSelection(
|
||||
baseOffset: 0, extentOffset: _currentPinController.text.length);
|
||||
_currentPinFocus.requestFocus();
|
||||
setState(() {
|
||||
_attemptsRemaining = attemptsRemaining;
|
||||
_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 currentPin = _currentPinController.text;
|
||||
final currentPinLen = byteLength(currentPin);
|
||||
final newPinLen = byteLength(_newPin);
|
||||
final newPin = _newPinController.text;
|
||||
final newPinLen = byteLength(newPin);
|
||||
final isValid = !_currentIsWrong &&
|
||||
_newPin.isNotEmpty &&
|
||||
_newPin == _confirmPin &&
|
||||
newPin.isNotEmpty &&
|
||||
newPin == _confirmPin &&
|
||||
currentPin.isNotEmpty;
|
||||
|
||||
final titleText = switch (widget.target) {
|
||||
@ -140,6 +162,10 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
||||
final showDefaultPukUsed =
|
||||
widget.target != ManageTarget.pin && _defaultPukUsed;
|
||||
|
||||
final hasPinComplexity =
|
||||
ref.read(currentDeviceDataProvider).valueOrNull?.info.pinComplexity ??
|
||||
false;
|
||||
|
||||
return ResponsiveDialog(
|
||||
title: Text(titleText),
|
||||
actions: [
|
||||
@ -213,21 +239,29 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
||||
});
|
||||
},
|
||||
).init(),
|
||||
Text(l10n.p_enter_new_piv_pin_puk(
|
||||
widget.target == ManageTarget.puk ? l10n.s_puk : l10n.s_pin)),
|
||||
Text(hasPinComplexity
|
||||
? 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(
|
||||
key: keys.newPinPukField,
|
||||
autofocus: showDefaultPinUsed || showDefaultPukUsed,
|
||||
obscureText: _isObscureNew,
|
||||
controller: _newPinController,
|
||||
focusNode: _newPinFocus,
|
||||
maxLength: 8,
|
||||
inputFormatters: [limitBytesLength(8)],
|
||||
buildCounter: buildByteCounterFor(_newPin),
|
||||
buildCounter: buildByteCounterFor(newPin),
|
||||
autofillHints: const [AutofillHints.newPassword],
|
||||
decoration: AppInputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: widget.target == ManageTarget.puk
|
||||
? l10n.s_new_puk
|
||||
: l10n.s_new_pin,
|
||||
errorText: _newIsWrong ? _newPinError : null,
|
||||
prefixIcon: const Icon(Symbols.password),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(_isObscureNew
|
||||
@ -247,7 +281,7 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
||||
textInputAction: TextInputAction.next,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_newPin = value;
|
||||
_newIsWrong = false;
|
||||
});
|
||||
},
|
||||
onSubmitted: (_) {
|
||||
@ -284,8 +318,9 @@ class _ManagePinPukDialogState extends ConsumerState<ManagePinPukDialog> {
|
||||
),
|
||||
enabled: currentPinLen >= _minPinLen && newPinLen >= 6,
|
||||
errorText:
|
||||
newPinLen == _confirmPin.length && _newPin != _confirmPin
|
||||
? (widget.target == ManageTarget.pin
|
||||
newPinLen == _confirmPin.length && newPin != _confirmPin
|
||||
? (widget.target == ManageTarget.pin ||
|
||||
widget.target == ManageTarget.unblock
|
||||
? l10n.l_pin_mismatch
|
||||
: l10n.l_puk_mismatch)
|
||||
: null,
|
||||
|
@ -60,14 +60,19 @@ class _PinDialogState extends ConsumerState<PinDialog> {
|
||||
success: () {
|
||||
navigator.pop(true);
|
||||
},
|
||||
failure: (attemptsRemaining) {
|
||||
_pinController.selection = TextSelection(
|
||||
baseOffset: 0, extentOffset: _pinController.text.length);
|
||||
_pinFocus.requestFocus();
|
||||
setState(() {
|
||||
_attemptsRemaining = attemptsRemaining;
|
||||
_pinIsWrong = true;
|
||||
});
|
||||
failure: (reason) {
|
||||
reason.maybeWhen(
|
||||
invalidPin: (attemptsRemaining) {
|
||||
_pinController.selection = TextSelection(
|
||||
baseOffset: 0, extentOffset: _pinController.text.length);
|
||||
_pinFocus.requestFocus();
|
||||
setState(() {
|
||||
_attemptsRemaining = attemptsRemaining;
|
||||
_pinIsWrong = true;
|
||||
});
|
||||
},
|
||||
orElse: () {},
|
||||
);
|
||||
},
|
||||
);
|
||||
} on CancellationException catch (_) {
|
||||
|
Loading…
Reference in New Issue
Block a user