Skip to content

Commit

Permalink
Update error handling and update package version
Browse files Browse the repository at this point in the history
  • Loading branch information
DDavidPrime committed Jul 19, 2024
1 parent edd6735 commit 4d97a83
Show file tree
Hide file tree
Showing 12 changed files with 57 additions and 36 deletions.
4 changes: 4 additions & 0 deletions packages/widget_toolkit_pin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## [0.1.0]
- Update `PinCodeService.verifyPinCode` to return a `Future<dynamic>` instead of a `bool`
- Improvements to error handling

## [0.0.2]
- Upgrade major versions of dependencies: `theme_tailor`, `theme_tailor_annotation`
### Breaking changes:
Expand Down
4 changes: 2 additions & 2 deletions packages/widget_toolkit_pin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,8 @@ ok, the biometrics authentication is triggered. When it is successful, on the sc
a message that the biometrics are enabled. The next time when restart the app, because the pin code
will be stored in the device secure storage, the biometrics authentication will be automatically
triggered and the biometrics icon will be displayed on the bottom right. When you press it every
time it will trigger the biometric authentication. If a user types a wrong pin code and the error
ErrorWrongPin is thrown from the service layer, then a shake animation is triggered on the masked
time it will trigger the biometric authentication. If a user types a wrong pin code and the error
is thrown from the service layer, then a shake animation is triggered on the masked
pin code and then the text from the ErrorWrongPin's errorMessage is displayed in the place of the
pin code. Note: If `biometricsLocalDataSource`parameter is not provided to `PinCodeKeyboard` the
biometrics authentication feature cannot be used.
Expand Down
28 changes: 20 additions & 8 deletions packages/widget_toolkit_pin/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class MyHomePage extends StatelessWidget {
addDependencies: true,
// Optionally you can provide [onAuthenticated] where the
// function is invoked when the user is authenticated.
onAuthenticated: () {
onAuthenticated: (authValue) {
_onAuthenticated(context);
},

Expand Down Expand Up @@ -126,7 +126,8 @@ class MyHomePage extends StatelessWidget {
);
}

String _translateError(Object error) => 'An error has occurred';
String _translateError(Object error) =>
error is ErrorModel ? error.toString() : 'An error has occurred';

String _exampleMapBiometricMessageToString(BiometricsMessage message) {
switch (message) {
Expand Down Expand Up @@ -156,7 +157,7 @@ class AppPinCodeService implements PinCodeService {

@override
Future<bool> isPinCodeInSecureStorage() async {
if (_pinCode == '111') {
if (_pinCode == '1111') {
return Future.value(true);
}
return Future.value(false);
Expand All @@ -169,14 +170,15 @@ class AppPinCodeService implements PinCodeService {
}

@override
Future<int> getPinLength() async => Future.value(3);
Future<int> getPinLength() async => Future.value(4);

@override
Future<bool> verifyPinCode(String pinCode) async {
if (pinCode == '111') {
return Future.value(true);
Future<dynamic> verifyPinCode(String pinCode) async {
if (pinCode != '1111') {
throw WrongPinCodeException(pinCode);
}
return false;

return pinCode;
}

@override
Expand Down Expand Up @@ -204,3 +206,13 @@ class ProfileLocalDataSource implements BiometricsLocalDataSource {
Future<void> setBiometricsEnabled(bool enable) async =>
_areBiometricsEnabled = enable;
}

/// Exception thrown when the pin code is wrong
class WrongPinCodeException implements ErrorModel {
final String pinCode;

WrongPinCodeException(this.pinCode);

@override
String toString() => 'Invalid pin code: $pinCode';
}
4 changes: 4 additions & 0 deletions packages/widget_toolkit_pin/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ dev_dependencies:
sdk: flutter
build_runner: ^2.4.6

dependency_overrides:
widget_toolkit_pin:
path: ..

flutter:
uses-material-design: true
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ abstract class PinCodeBlocStates {
ConnectableStream<bool> get showBiometricsButton;

///Emits when user successfully authenticate (pin/biometrics)
ConnectableStream<void> get authenticated;
ConnectableStream<dynamic> get authenticated;

/// The loading state
Stream<bool> get isLoading;
Expand All @@ -56,9 +56,9 @@ class PinCodeBloc extends $PinCodeBloc {
final String localizedReason;

final BehaviorSubject<String> _pinCode = BehaviorSubject.seeded('');
final BehaviorSubject<bool> _pinAuth = BehaviorSubject();
final BehaviorSubject<dynamic> _pinAuth = BehaviorSubject();

Future<bool> encryptAndVerify(String pinCode) async {
Future<dynamic> encryptAndVerify(String pinCode) async {
final encryptedPin = await pinCodeService.encryptPinCode(pinCode);
final verifiedPin = await pinCodeService.verifyPinCode(encryptedPin);
return verifiedPin;
Expand Down Expand Up @@ -91,7 +91,7 @@ class PinCodeBloc extends $PinCodeBloc {
Stream<ErrorModel> _mapToErrorsState() => errorState.mapToErrorModel();

@override
ConnectableStream<void> _mapToAuthenticatedState() => Rx.merge([
ConnectableStream<dynamic> _mapToAuthenticatedState() => Rx.merge([
_$biometricsButtonPressedEvent.switchMap((_) =>
biometricAuthenticationService
.authenticate(localizedReason)
Expand Down Expand Up @@ -127,16 +127,16 @@ class PinCodeBloc extends $PinCodeBloc {
Future<bool> _checkPin(int digits) async {
final storedPinLength = await pinCodeService.getPinLength();
if (digits == storedPinLength) {
final isCorrectPin = await encryptAndVerify(_pinCode.value);
if (isCorrectPin) {
try {
final authValue = await encryptAndVerify(_pinCode.value);
final isSaved = await pinCodeService.isPinCodeInSecureStorage();
if (isSaved) {
_pinAuth.add(true);
_pinAuth.add(authValue);
return true;
}
} else {
} catch (_) {
_pinCode.value = '';
throw Exception('Wrong Pin');
rethrow;
}
}
return false;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ abstract class PinCodeService {
Future<bool> isPinCodeInSecureStorage();

/// Receives the encrypted pinCode from user input.
/// Returns whether it was verified by the server
Future<bool> verifyPinCode(String pinCode);
/// Returns the value verified by the server
Future<dynamic> verifyPinCode(String pinCode);

/// Returns the correct length from the backend,
/// the length should be less than 10 digits
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class PinCodeComponent extends StatefulWidget {
final String Function(BiometricsMessage message)? mapBiometricMessageToString;

/// Returns the verification state of the input from the pin code value.
final VoidCallback? onAuthenticated;
final Function(dynamic)? onAuthenticated;

/// Provide custom implementation for the most down left button. Do not forget
/// to make it clickable. Default to LeftArrow.
Expand Down Expand Up @@ -161,13 +161,14 @@ class _PinCodeComponentState extends State<PinCodeComponent>
_startErrorAnimation();
},
),
RxBlocListener<PinCodeBlocType, void>(
RxBlocListener<PinCodeBlocType, dynamic>(
state: (bloc) => bloc.states.authenticated,
listener: (context, auth) {
listener: (context, authValue) {
setState(() {
authenticatedPin = true;
});
widget.onAuthenticated?.call();

widget.onAuthenticated?.call(authValue);
},
),
_buildBuilders()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class PinCodeKeyboard extends StatelessWidget {
final BiometricsLocalDataSource? biometricsLocalDataSource;

/// Called when a user is authenticated with biometrics successfully
final VoidCallback? onAuthenticated;
final Function(dynamic)? onAuthenticated;

/// Provide custom implementation for the most down left button, shown when
/// there is pin code input on the screen. Do not forget to make it clickable.
Expand Down
2 changes: 1 addition & 1 deletion packages/widget_toolkit_pin/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: widget_toolkit_pin
description: This package provide out of the box entering PIN code
functionality, which can be used with biometric authentication.
version: 0.0.2
version: 0.1.0
homepage: https://primeholding.com/

environment:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,13 @@ class MockPinCodeService extends _i1.Mock implements _i7.PinCodeService {
) as _i4.Future<bool>);

@override
_i4.Future<bool> verifyPinCode(String? pinCode) => (super.noSuchMethod(
_i4.Future<dynamic> verifyPinCode(String? pinCode) => (super.noSuchMethod(
Invocation.method(
#verifyPinCode,
[pinCode],
),
returnValue: _i4.Future<bool>.value(false),
) as _i4.Future<bool>);
returnValue: _i4.Future<dynamic>.value(),
) as _i4.Future<dynamic>);

@override
_i4.Future<int> getPinLength() => (super.noSuchMethod(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,13 @@ class MockPinCodeBlocStates extends _i1.Mock implements _i3.PinCodeBlocStates {
) as _i2.ConnectableStream<bool>);

@override
_i2.ConnectableStream<void> get authenticated => (super.noSuchMethod(
_i2.ConnectableStream<dynamic> get authenticated => (super.noSuchMethod(
Invocation.getter(#authenticated),
returnValue: _FakeConnectableStream_0<void>(
returnValue: _FakeConnectableStream_0<dynamic>(
this,
Invocation.getter(#authenticated),
),
) as _i2.ConnectableStream<void>);
) as _i2.ConnectableStream<dynamic>);

@override
_i4.Stream<bool> get isLoading => (super.noSuchMethod(
Expand Down

0 comments on commit 4d97a83

Please sign in to comment.