master #81
@ -16,7 +16,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import 'dart:async';
 | 
					import 'dart:async';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:rxdart/rxdart.dart';
 | 
					 | 
				
			||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
 | 
					import 'package:wyatt_architecture/wyatt_architecture.dart';
 | 
				
			||||||
import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart';
 | 
					import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart';
 | 
				
			||||||
import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart';
 | 
					import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart';
 | 
				
			||||||
@ -25,37 +24,25 @@ import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authenti
 | 
				
			|||||||
import 'package:wyatt_authentication_bloc/src/domain/data_sources/remote/authentication_remote_data_source.dart';
 | 
					import 'package:wyatt_authentication_bloc/src/domain/data_sources/remote/authentication_remote_data_source.dart';
 | 
				
			||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
 | 
					import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
 | 
				
			||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart';
 | 
					import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_authentication_bloc/src/domain/entities/auth_change_event.dart';
 | 
				
			||||||
import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart';
 | 
					import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart';
 | 
				
			||||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
 | 
					import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
 | 
				
			||||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
 | 
					import 'package:wyatt_type_utils/wyatt_type_utils.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef OnSignUpSuccess<T> = FutureOrResult<T?> Function(
 | 
					 | 
				
			||||||
  AuthenticationRepository<T> repo,
 | 
					 | 
				
			||||||
  Account? account,
 | 
					 | 
				
			||||||
  WyattForm form,
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef OnAuthChange<T> = FutureOrResult<T?> Function(
 | 
					 | 
				
			||||||
  AuthenticationRepository<T> repo,
 | 
					 | 
				
			||||||
  Account? account,
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AuthenticationRepositoryImpl<T extends Object>
 | 
					class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			||||||
    extends AuthenticationRepository<T> {
 | 
					    extends AuthenticationRepository<T> {
 | 
				
			||||||
  AuthenticationRepositoryImpl({
 | 
					  AuthenticationRepositoryImpl({
 | 
				
			||||||
    required AuthenticationCacheDataSource<T> authenticationCacheDataSource,
 | 
					    required this.authenticationCacheDataSource,
 | 
				
			||||||
    required AuthenticationRemoteDataSource authenticationRemoteDataSource,
 | 
					    required this.authenticationRemoteDataSource,
 | 
				
			||||||
    FormRepository? formRepository,
 | 
					    FormRepository? formRepository,
 | 
				
			||||||
    // ignore: strict_raw_type
 | 
					    // ignore: strict_raw_type
 | 
				
			||||||
    List<FormInput>? extraSignUpInputs,
 | 
					    List<FormInput>? extraSignUpInputs,
 | 
				
			||||||
    FormInputValidator<String?, ValidationError>? customEmailValidator,
 | 
					    FormInputValidator<String?, ValidationError>? customEmailValidator,
 | 
				
			||||||
    FormInputValidator<String?, ValidationError>? customPasswordValidator,
 | 
					    FormInputValidator<String?, ValidationError>? customPasswordValidator,
 | 
				
			||||||
    OnSignUpSuccess<T>? onSignUpSuccess,
 | 
					    AuthChangeListener<T>? onAuthChange,
 | 
				
			||||||
    OnAuthChange<T>? onAuthChange,
 | 
					    AccountStreamTransformer<T>? accountStreamTransformer,
 | 
				
			||||||
  })  : _authenticationLocalDataSource = authenticationCacheDataSource,
 | 
					  })  : _authChangeListener = onAuthChange,
 | 
				
			||||||
        _authenticationRemoteDataSource = authenticationRemoteDataSource,
 | 
					        _accountStreamTransformer = accountStreamTransformer {
 | 
				
			||||||
        _onSignUpSuccess = onSignUpSuccess,
 | 
					 | 
				
			||||||
        _onAccountChanges = onAuthChange {
 | 
					 | 
				
			||||||
    _formRepository = formRepository ?? FormRepositoryImpl();
 | 
					    _formRepository = formRepository ?? FormRepositoryImpl();
 | 
				
			||||||
    if (formRepository != null) {
 | 
					    if (formRepository != null) {
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
@ -103,23 +90,34 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
          name: AuthFormName.passwordResetForm,
 | 
					          name: AuthFormName.passwordResetForm,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					    _accountStreamTransformer ??= (input) => input
 | 
				
			||||||
 | 
					            .where((event) => event is! SignUpAuthChangeEvent)
 | 
				
			||||||
 | 
					            .map<FutureOrResult<AccountWrapper<T>>>((event) async {
 | 
				
			||||||
 | 
					          if (listener == null) {
 | 
				
			||||||
 | 
					            return Ok(AccountWrapperModel<T>(event.account, null));
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          // Handle sign in, sign out and refresh
 | 
				
			||||||
 | 
					          final dataResult = await listener!.call(this, event);
 | 
				
			||||||
 | 
					          return dataResult.map((data) {
 | 
				
			||||||
 | 
					            authenticationCacheDataSource.storeData(data);
 | 
				
			||||||
 | 
					            return AccountWrapperModel(event.account, data);
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  final AuthenticationCacheDataSource<T> _authenticationLocalDataSource;
 | 
					  final AuthenticationCacheDataSource<T> authenticationCacheDataSource;
 | 
				
			||||||
  final AuthenticationRemoteDataSource _authenticationRemoteDataSource;
 | 
					  final AuthenticationRemoteDataSource authenticationRemoteDataSource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  late FormRepository _formRepository;
 | 
					  late FormRepository _formRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final OnSignUpSuccess<T>? _onSignUpSuccess;
 | 
					  AuthChangeListener<T>? _authChangeListener;
 | 
				
			||||||
 | 
					  AccountStreamTransformer<T>? _accountStreamTransformer;
 | 
				
			||||||
  final OnAuthChange<T>? _onAccountChanges;
 | 
					 | 
				
			||||||
  final StreamController<FutureOrResult<AccountWrapper<T>>> _signUpStream =
 | 
					 | 
				
			||||||
      StreamController();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool _pause = false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  FormRepository get formRepository => _formRepository;
 | 
					  FormRepository get formRepository => _formRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  AuthChangeListener<T>? get listener => _authChangeListener;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  FutureOrResult<Account> signInWithEmailAndPassword({
 | 
					  FutureOrResult<Account> signInWithEmailAndPassword({
 | 
				
			||||||
    required String email,
 | 
					    required String email,
 | 
				
			||||||
@ -128,11 +126,11 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
					      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          final account =
 | 
					          final account =
 | 
				
			||||||
              await _authenticationRemoteDataSource.signInWithEmailAndPassword(
 | 
					              await authenticationRemoteDataSource.signInWithEmailAndPassword(
 | 
				
			||||||
            email: email,
 | 
					            email: email,
 | 
				
			||||||
            password: password,
 | 
					            password: password,
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
          await _authenticationLocalDataSource.storeAccount(account);
 | 
					          await authenticationCacheDataSource.storeAccount(account);
 | 
				
			||||||
          return account;
 | 
					          return account;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
@ -142,8 +140,8 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  FutureOrResult<void> signOut() =>
 | 
					  FutureOrResult<void> signOut() =>
 | 
				
			||||||
      Result.tryCatchAsync<void, AppException, AppException>(
 | 
					      Result.tryCatchAsync<void, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          await _authenticationRemoteDataSource.signOut();
 | 
					          await authenticationRemoteDataSource.signOut();
 | 
				
			||||||
          await _authenticationLocalDataSource.destroy();
 | 
					          await authenticationCacheDataSource.destroy();
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -155,54 +153,34 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  }) =>
 | 
					  }) =>
 | 
				
			||||||
      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
					      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          _pause = true;
 | 
					          final account = await authenticationRemoteDataSource.signUp(
 | 
				
			||||||
          final account = await _authenticationRemoteDataSource.signUp(
 | 
					 | 
				
			||||||
            email: email,
 | 
					            email: email,
 | 
				
			||||||
            password: password,
 | 
					            password: password,
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
          await _authenticationLocalDataSource.storeAccount(account);
 | 
					          await authenticationCacheDataSource.storeAccount(account);
 | 
				
			||||||
          if (_onSignUpSuccess.isNotNull) {
 | 
					 | 
				
			||||||
            final dataResult = await _onSignUpSuccess!.call(
 | 
					 | 
				
			||||||
              this,
 | 
					 | 
				
			||||||
              account,
 | 
					 | 
				
			||||||
              _formRepository.accessForm(AuthFormName.signUpForm).clone(),
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            await dataResult.foldAsync(
 | 
					 | 
				
			||||||
              (data) async {
 | 
					 | 
				
			||||||
                await _authenticationLocalDataSource.storeData(data);
 | 
					 | 
				
			||||||
                _signUpStream
 | 
					 | 
				
			||||||
                    .add(Future.value(Ok(AccountWrapperModel(account, data))));
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              (error) async => error,
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          _pause = false;
 | 
					 | 
				
			||||||
          return account;
 | 
					          return account;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        (error) {
 | 
					        (error) => error,
 | 
				
			||||||
          _pause = false;
 | 
					 | 
				
			||||||
          return error;
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  FutureOrResult<void> destroyCache() =>
 | 
					  FutureOrResult<void> destroyCache() =>
 | 
				
			||||||
      Result.tryCatchAsync<void, AppException, AppException>(
 | 
					      Result.tryCatchAsync<void, AppException, AppException>(
 | 
				
			||||||
        _authenticationLocalDataSource.destroy,
 | 
					        authenticationCacheDataSource.destroy,
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  FutureOrResult<AccountWrapper<T>> getCache() =>
 | 
					  FutureOrResult<AccountWrapper<T>> getCache() =>
 | 
				
			||||||
      Result.tryCatchAsync<AccountWrapper<T>, AppException, AppException>(
 | 
					      Result.tryCatchAsync<AccountWrapper<T>, AppException, AppException>(
 | 
				
			||||||
        _authenticationLocalDataSource.load,
 | 
					        authenticationCacheDataSource.load,
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  FutureOrResult<Account> getAccount() =>
 | 
					  FutureOrResult<Account> getAccount() =>
 | 
				
			||||||
      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
					      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
				
			||||||
        _authenticationLocalDataSource.loadAccount,
 | 
					        authenticationCacheDataSource.loadAccount,
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -212,7 +190,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  ) =>
 | 
					  ) =>
 | 
				
			||||||
      Result.tryCatchAsync<void, AppException, AppException>(
 | 
					      Result.tryCatchAsync<void, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          await _authenticationLocalDataSource.storeAccount(account);
 | 
					          await authenticationCacheDataSource.storeAccount(account);
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -220,7 +198,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  FutureOrResult<T> getData() =>
 | 
					  FutureOrResult<T> getData() =>
 | 
				
			||||||
      Result.tryCatchAsync<T, AppException, AppException>(
 | 
					      Result.tryCatchAsync<T, AppException, AppException>(
 | 
				
			||||||
        _authenticationLocalDataSource.loadData,
 | 
					        authenticationCacheDataSource.loadData,
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -230,7 +208,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  ) =>
 | 
					  ) =>
 | 
				
			||||||
      Result.tryCatchAsync<void, AppException, AppException>(
 | 
					      Result.tryCatchAsync<void, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          await _authenticationLocalDataSource.storeData(data);
 | 
					          await authenticationCacheDataSource.storeData(data);
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -238,26 +216,13 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  FutureOrResult<String> getIdentityToken() =>
 | 
					  FutureOrResult<String> getIdentityToken() =>
 | 
				
			||||||
      Result.tryCatchAsync<String, AppException, AppException>(
 | 
					      Result.tryCatchAsync<String, AppException, AppException>(
 | 
				
			||||||
        _authenticationRemoteDataSource.getIdentityToken,
 | 
					        authenticationRemoteDataSource.getIdentityToken,
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Stream<FutureOrResult<AccountWrapper<T>>> streamAccount() => MergeStream([
 | 
					  Stream<FutureOrResult<AccountWrapper<T>>> streamAccount() =>
 | 
				
			||||||
        _signUpStream.stream.asBroadcastStream(),
 | 
					      _accountStreamTransformer!.call(changes());
 | 
				
			||||||
        _authenticationRemoteDataSource.streamAccount().map((account) async {
 | 
					 | 
				
			||||||
          if (_onAccountChanges.isNotNull && !_pause) {
 | 
					 | 
				
			||||||
            final dataResult = await _onAccountChanges!.call(this, account);
 | 
					 | 
				
			||||||
            return dataResult.map((data) {
 | 
					 | 
				
			||||||
              _authenticationLocalDataSource.storeData(data);
 | 
					 | 
				
			||||||
              return AccountWrapperModel(account, data);
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          return Ok<AccountWrapperModel<T>, AppException>(
 | 
					 | 
				
			||||||
            AccountWrapperModel<T>(account, null),
 | 
					 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
      ]);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  FutureOrResult<void> confirmPasswordReset({
 | 
					  FutureOrResult<void> confirmPasswordReset({
 | 
				
			||||||
@ -266,7 +231,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  }) =>
 | 
					  }) =>
 | 
				
			||||||
      Result.tryCatchAsync<void, AppException, AppException>(
 | 
					      Result.tryCatchAsync<void, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          await _authenticationRemoteDataSource.confirmPasswordReset(
 | 
					          await authenticationRemoteDataSource.confirmPasswordReset(
 | 
				
			||||||
            code: code,
 | 
					            code: code,
 | 
				
			||||||
            newPassword: newPassword,
 | 
					            newPassword: newPassword,
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
@ -278,7 +243,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  FutureOrResult<void> sendEmailVerification() =>
 | 
					  FutureOrResult<void> sendEmailVerification() =>
 | 
				
			||||||
      Result.tryCatchAsync<void, AppException, AppException>(
 | 
					      Result.tryCatchAsync<void, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          await _authenticationRemoteDataSource.sendEmailVerification();
 | 
					          await authenticationRemoteDataSource.sendEmailVerification();
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -287,7 +252,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  FutureOrResult<void> sendPasswordResetEmail({required String email}) =>
 | 
					  FutureOrResult<void> sendPasswordResetEmail({required String email}) =>
 | 
				
			||||||
      Result.tryCatchAsync<void, AppException, AppException>(
 | 
					      Result.tryCatchAsync<void, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          await _authenticationRemoteDataSource.sendPasswordResetEmail(
 | 
					          await authenticationRemoteDataSource.sendPasswordResetEmail(
 | 
				
			||||||
            email: email,
 | 
					            email: email,
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
@ -299,7 +264,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
					      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          final account =
 | 
					          final account =
 | 
				
			||||||
              await _authenticationRemoteDataSource.signInAnonymously();
 | 
					              await authenticationRemoteDataSource.signInAnonymously();
 | 
				
			||||||
          return account;
 | 
					          return account;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
@ -310,7 +275,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
					      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          final account =
 | 
					          final account =
 | 
				
			||||||
              await _authenticationRemoteDataSource.signInWithGoogle();
 | 
					              await authenticationRemoteDataSource.signInWithGoogle();
 | 
				
			||||||
          return account;
 | 
					          return account;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
@ -320,7 +285,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  FutureOrResult<bool> verifyPasswordResetCode({required String code}) =>
 | 
					  FutureOrResult<bool> verifyPasswordResetCode({required String code}) =>
 | 
				
			||||||
      Result.tryCatchAsync<bool, AppException, AppException>(
 | 
					      Result.tryCatchAsync<bool, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          final response = await _authenticationRemoteDataSource
 | 
					          final response = await authenticationRemoteDataSource
 | 
				
			||||||
              .verifyPasswordResetCode(code: code);
 | 
					              .verifyPasswordResetCode(code: code);
 | 
				
			||||||
          return response;
 | 
					          return response;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
@ -331,7 +296,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  FutureOrResult<void> refresh() =>
 | 
					  FutureOrResult<void> refresh() =>
 | 
				
			||||||
      Result.tryCatchAsync<void, AppException, AppException>(
 | 
					      Result.tryCatchAsync<void, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          await _authenticationRemoteDataSource.refresh();
 | 
					          await authenticationRemoteDataSource.refresh();
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -340,7 +305,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  FutureOrResult<Account> reauthenticateWithCredential() =>
 | 
					  FutureOrResult<Account> reauthenticateWithCredential() =>
 | 
				
			||||||
      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
					      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          final account = await _authenticationRemoteDataSource
 | 
					          final account = await authenticationRemoteDataSource
 | 
				
			||||||
              .reauthenticateWithCredential();
 | 
					              .reauthenticateWithCredential();
 | 
				
			||||||
          return account;
 | 
					          return account;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
@ -352,7 +317,7 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
					      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          final account =
 | 
					          final account =
 | 
				
			||||||
              await _authenticationRemoteDataSource.updateEmail(email: email);
 | 
					              await authenticationRemoteDataSource.updateEmail(email: email);
 | 
				
			||||||
          return account;
 | 
					          return account;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
@ -362,11 +327,52 @@ class AuthenticationRepositoryImpl<T extends Object>
 | 
				
			|||||||
  FutureOrResult<Account> updatePassword({required String password}) =>
 | 
					  FutureOrResult<Account> updatePassword({required String password}) =>
 | 
				
			||||||
      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
					      Result.tryCatchAsync<Account, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          final account = await _authenticationRemoteDataSource.updatePassword(
 | 
					          final account = await authenticationRemoteDataSource.updatePassword(
 | 
				
			||||||
            password: password,
 | 
					            password: password,
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
          return account;
 | 
					          return account;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        (error) => error,
 | 
					        (error) => error,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Account? _lastChange;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Stream<AuthChangeEvent> changes() => authenticationRemoteDataSource
 | 
				
			||||||
 | 
					          .streamAccount()
 | 
				
			||||||
 | 
					          .map<AuthChangeEvent>((account) {
 | 
				
			||||||
 | 
					        if (_lastChange != null && account == null) {
 | 
				
			||||||
 | 
					          _lastChange = null;
 | 
				
			||||||
 | 
					          return SignOutAuthChangeEvent();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (_lastChange == null && account != null) {
 | 
				
			||||||
 | 
					          _lastChange = account;
 | 
				
			||||||
 | 
					          if (account.isNewUser ?? false) {
 | 
				
			||||||
 | 
					            return SignUpAuthChangeEvent(account);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          return SignInAuthChangeEvent(account);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (_lastChange != null && account != null) {
 | 
				
			||||||
 | 
					          _lastChange = account;
 | 
				
			||||||
 | 
					          return RefreshAuthChangeEvent(account);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (_lastChange == null && account == null) {
 | 
				
			||||||
 | 
					          _lastChange = account;
 | 
				
			||||||
 | 
					          return StillUnauthenticatedAuthChangeEvent();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        _lastChange = account;
 | 
				
			||||||
 | 
					        return RefreshAuthChangeEvent(account);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  FutureOrResult<void> addAuthChangeListener(AuthChangeListener<T> listener) {
 | 
				
			||||||
 | 
					    _authChangeListener = listener;
 | 
				
			||||||
 | 
					    return const Ok(null);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  FutureOrResult<void> removeAuthChangeListener() {
 | 
				
			||||||
 | 
					    _authChangeListener = null;
 | 
				
			||||||
 | 
					    return const Ok(null);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					// 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 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class AuthChangeEvent {
 | 
				
			||||||
 | 
					  AuthChangeEvent(this.account);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final Account? account;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SignInAuthChangeEvent extends AuthChangeEvent {
 | 
				
			||||||
 | 
					  SignInAuthChangeEvent(super.account);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SignUpAuthChangeEvent extends AuthChangeEvent {
 | 
				
			||||||
 | 
					  SignUpAuthChangeEvent(super.account);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RefreshAuthChangeEvent extends AuthChangeEvent {
 | 
				
			||||||
 | 
					  RefreshAuthChangeEvent(super.account);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class StillUnauthenticatedAuthChangeEvent extends AuthChangeEvent {
 | 
				
			||||||
 | 
					  StillUnauthenticatedAuthChangeEvent() : super(null);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SignOutAuthChangeEvent extends AuthChangeEvent {
 | 
				
			||||||
 | 
					  SignOutAuthChangeEvent() : super(null);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -16,3 +16,4 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export 'account.dart';
 | 
					export 'account.dart';
 | 
				
			||||||
export 'account_wrapper.dart';
 | 
					export 'account_wrapper.dart';
 | 
				
			||||||
 | 
					export 'auth_change_event.dart';
 | 
				
			||||||
 | 
				
			|||||||
@ -17,10 +17,28 @@
 | 
				
			|||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
 | 
					import 'package:wyatt_architecture/wyatt_architecture.dart';
 | 
				
			||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
 | 
					import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
 | 
				
			||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart';
 | 
					import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_authentication_bloc/src/domain/entities/auth_change_event.dart';
 | 
				
			||||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
 | 
					import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef SignUpCallback<T> = FutureOrResult<T?> Function(
 | 
				
			||||||
 | 
					  AuthenticationRepository<T> repo,
 | 
				
			||||||
 | 
					  Account? account,
 | 
				
			||||||
 | 
					  WyattForm form,
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef AuthChangeListener<T> = FutureOrResult<T?> Function(
 | 
				
			||||||
 | 
					  AuthenticationRepository<T> repo,
 | 
				
			||||||
 | 
					  AuthChangeEvent? authEvent,
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef AccountStreamTransformer<T extends Object>
 | 
				
			||||||
 | 
					    = Stream<FutureOrResult<AccountWrapper<T>>> Function(
 | 
				
			||||||
 | 
					  Stream<AuthChangeEvent> input,
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
abstract class AuthenticationRepository<T> extends BaseRepository {
 | 
					abstract class AuthenticationRepository<T> extends BaseRepository {
 | 
				
			||||||
  FormRepository get formRepository;
 | 
					  FormRepository get formRepository;
 | 
				
			||||||
 | 
					  AuthChangeListener<T>? get listener;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// {@template signup}
 | 
					  /// {@template signup}
 | 
				
			||||||
  /// Creates a new user with the provided [email] and [password].
 | 
					  /// Creates a new user with the provided [email] and [password].
 | 
				
			||||||
@ -141,6 +159,8 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
 | 
				
			|||||||
  /// {@endtemplate}
 | 
					  /// {@endtemplate}
 | 
				
			||||||
  Stream<FutureOrResult<AccountWrapper<T>>> streamAccount();
 | 
					  Stream<FutureOrResult<AccountWrapper<T>>> streamAccount();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Stream<AuthChangeEvent> changes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FutureOrResult<String> getIdentityToken();
 | 
					  FutureOrResult<String> getIdentityToken();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FutureOrResult<Account> getAccount();
 | 
					  FutureOrResult<Account> getAccount();
 | 
				
			||||||
@ -151,4 +171,7 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  FutureOrResult<AccountWrapper<T>> getCache();
 | 
					  FutureOrResult<AccountWrapper<T>> getCache();
 | 
				
			||||||
  FutureOrResult<void> destroyCache();
 | 
					  FutureOrResult<void> destroyCache();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  FutureOrResult<void> addAuthChangeListener(AuthChangeListener<T> listener);
 | 
				
			||||||
 | 
					  FutureOrResult<void> removeAuthChangeListener();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user