feat(auth): add fully functionnal mock data source

This commit is contained in:
Hugo Pointcheval 2022-11-11 18:48:30 -05:00
parent da34acd35b
commit 87254ef547
Signed by: hugo
GPG Key ID: A9E8E9615379254F
5 changed files with 234 additions and 7 deletions

View File

@ -16,6 +16,7 @@
import 'package:get_it/get_it.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
final getIt = GetIt.I;
@ -23,12 +24,33 @@ abstract class GetItInitializer {
static Future<void> init() async {
getIt
..registerLazySingleton<AuthenticationRemoteDataSource>(
() => AuthenticationFirebaseDataSourceImpl(),
() => AuthenticationMockDataSourceImpl(registeredAccounts: [
Pair(
AccountModel(
uid: '1',
emailVerified: true,
isAnonymous: false,
providerId: 'wyatt',
email: 'toto@test.fr',
),
'toto1234',
),
Pair(
AccountModel(
uid: '2',
emailVerified: false,
isAnonymous: false,
providerId: 'wyatt',
email: 'tata@test.fr',
),
'tata1234',
),
]),
)
..registerLazySingleton<AuthenticationCacheDataSource<int>>(
() => AuthenticationCacheDataSourceImpl<int>(),
);
await getIt.allReady();
}
}

View File

@ -72,7 +72,7 @@ class SignInForm extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SignInListener(
return SignInListener<int>(
onError: (context, status, errorMessage) => ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(

View File

@ -109,7 +109,7 @@ class SignUpForm extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SignUpListener(
return SignUpListener<int>(
onError: (context, status, errorMessage) =>
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()

View File

@ -1,18 +1,19 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'local/authentication_cache_data_source_impl.dart';
export 'remote/authentication_firebase_data_source_impl.dart';
export 'remote/authentication_mock_data_source_impl.dart';

View File

@ -0,0 +1,204 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:async';
import 'dart:math';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
Pair<Account, String>? _connectedMock;
Pair<Account, String>? _registeredMock;
final StreamController<Account?> _streamAccount = StreamController();
final List<Pair<Account, String>>? registeredAccounts;
final String idToken;
AuthenticationMockDataSourceImpl({
this.idToken = 'fake-id-token',
this.registeredAccounts,
});
Future<void> _randomDelay() async {
await Future<void>.delayed(
Duration(milliseconds: Random().nextInt(400) + 200),
);
return;
}
@override
Future<void> confirmPasswordReset({
required String code,
required String newPassword,
}) async {
await _randomDelay();
}
@override
Future<String> getIdentityToken() async {
await _randomDelay();
return idToken;
}
@override
Future<void> refresh() async {
await _randomDelay();
if (_connectedMock.isNull) {
throw RefreshFailureFirebase();
}
final refresh = DateTime.now();
final mock = (_connectedMock?.left as AccountModel?)
?.copyWith(lastSignInTime: refresh);
_connectedMock = _connectedMock?.copyWith(left: mock);
_streamAccount.add(mock);
}
@override
Future<void> sendEmailVerification() async {
await _randomDelay();
if (_connectedMock.isNotNull) {
final refresh = DateTime.now();
final mock = (_connectedMock?.left as AccountModel?)?.copyWith(
emailVerified: false,
lastSignInTime: refresh,
);
_streamAccount.add(mock);
_connectedMock = _connectedMock?.copyWith(left: mock);
return;
}
throw SendEmailVerificationFailureFirebase();
}
@override
Future<void> sendPasswordResetEmail({required String email}) async {
await _randomDelay();
if (registeredAccounts.isNotNull) {
final accounts =
registeredAccounts?.where((pair) => pair.left?.email == email);
if (accounts.isNotNullOrEmpty) {
return;
}
}
if (_registeredMock.isNotNull) {
if (_registeredMock?.left?.email != email) {
throw SendPasswordResetEmailFailureFirebase();
}
return;
}
throw SendPasswordResetEmailFailureFirebase();
}
@override
Future<Account> signInAnonymously() async {
await _randomDelay();
final creation = DateTime.now();
final mock = AccountModel(
uid: 'mock-id-anom',
emailVerified: false,
isAnonymous: true,
providerId: 'wyatt',
creationTime: creation,
lastSignInTime: creation,
);
_streamAccount.add(mock);
_connectedMock = _connectedMock?.copyWith(left: mock);
return Future.value(mock);
}
@override
Future<Account> signInWithEmailAndPassword({
required String email,
required String password,
}) async {
await _randomDelay();
if (registeredAccounts.isNotNull) {
final accounts =
registeredAccounts?.where((pair) => pair.left?.email == email);
if (accounts.isNotNullOrEmpty) {
final account = accounts?.first;
if (account?.right != password) {
throw SignInWithCredentialFailureFirebase.fromCode('wrong-password');
}
_streamAccount.add(account!.left);
_connectedMock = account.copyWith();
return account.left!;
}
}
if (_registeredMock.isNotNull) {
if (_registeredMock?.left?.email != email) {
throw SignInWithCredentialFailureFirebase.fromCode('user-not-found');
}
if (_registeredMock?.right != password) {
throw SignInWithCredentialFailureFirebase.fromCode('wrong-password');
}
_streamAccount.add(_registeredMock!.left);
_connectedMock = _registeredMock!.copyWith();
return _registeredMock!.left!;
}
throw SignInWithCredentialFailureFirebase();
}
@override
Future<void> signOut() async {
_connectedMock = null;
_streamAccount.add(null);
}
@override
Future<Account> signUp({
required String email,
required String password,
}) async {
await _randomDelay();
if (registeredAccounts.isNotNull) {
final accounts =
registeredAccounts?.where((pair) => pair.left?.email == email);
if (accounts.isNotNullOrEmpty) {
throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(
'email-already-in-use',
);
}
}
if (_registeredMock?.left?.email == email) {
throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(
'email-already-in-use',
);
}
final creation = DateTime.now();
final mock = AccountModel(
uid: 'mock-id-email',
emailVerified: false,
isAnonymous: false,
providerId: 'wyatt',
email: email,
creationTime: creation,
lastSignInTime: creation,
);
_streamAccount.add(mock);
_registeredMock = Pair(mock, password);
return Future.value(mock);
}
@override
Stream<Account?> streamAccount() => _streamAccount.stream.asBroadcastStream();
@override
Future<bool> verifyPasswordResetCode({required String code}) async {
await _randomDelay();
return true;
}
}