refactor(authentication)!: split data sources (cache, session, external)
This commit is contained in:
		
							parent
							
								
									5a7930550d
								
							
						
					
					
						commit
						d53e7b80da
					
				| @ -14,4 +14,5 @@ | ||||
| // 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 'remote/authentication_firebase_data_source_impl.dart'; | ||||
| export 'local/local.dart'; | ||||
| export 'remote/remote.dart'; | ||||
|  | ||||
| @ -0,0 +1,56 @@ | ||||
| // Copyright (C) 2023 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/data_sources/local/authentication_cache_data_source.dart'; | ||||
| import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; | ||||
| 
 | ||||
| /// {@template authentication_firebase_cache_data_source_impl} | ||||
| /// A data source that manages the cache strategy. | ||||
| /// This implementation uses Firebase. | ||||
| /// {@endtemplate} | ||||
| class AuthenticationFirebaseCacheDataSourceImpl<Data> | ||||
|     extends AuthenticationCacheDataSource<Data> { | ||||
|   /// {@macro authentication_firebase_cache_data_source_impl} | ||||
|   AuthenticationFirebaseCacheDataSourceImpl({ | ||||
|     FirebaseAuth? firebaseAuth, | ||||
|   }) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance; | ||||
| 
 | ||||
|   final FirebaseAuth _firebaseAuth; | ||||
| 
 | ||||
|   // Already done by Firebase | ||||
|   @override | ||||
|   Future<void> cacheAccount(Account account) => Future.value(); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Account?> getCachedAccount() async { | ||||
|     final currentUser = _firebaseAuth.currentUser; | ||||
|     if (currentUser == null) { | ||||
|       return null; | ||||
|     } | ||||
| 
 | ||||
|     final jwt = await currentUser.getIdToken(true); | ||||
|     final currentAccount = AccountModel.fromFirebaseUser( | ||||
|       currentUser, | ||||
|       accessToken: jwt, | ||||
|     ); | ||||
| 
 | ||||
|     return currentAccount; | ||||
|   } | ||||
| 
 | ||||
|   // Already done by Firebase | ||||
|   @override | ||||
|   Future<void> removeCachedAccount() => Future.value(); | ||||
| } | ||||
| @ -0,0 +1,45 @@ | ||||
| // Copyright (C) 2023 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 'package:rxdart/subjects.dart'; | ||||
| import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_session_data_source.dart'; | ||||
| import 'package:wyatt_authentication_bloc/src/domain/entities/auth_session.dart'; | ||||
| 
 | ||||
| /// {@template authentication_session_data_source_impl} | ||||
| /// A data source that manages the current session. | ||||
| /// {@endtemplate} | ||||
| class AuthenticationSessionDataSourceImpl<Data> | ||||
|     extends AuthenticationSessionDataSource<Data> { | ||||
|   /// {@macro authentication_session_data_source_impl} | ||||
|   AuthenticationSessionDataSourceImpl(); | ||||
| 
 | ||||
|   final StreamController<AuthenticationSession<Data>> _sessionStream = | ||||
|       BehaviorSubject(); | ||||
| 
 | ||||
|   @override | ||||
|   void addSession(AuthenticationSession<Data> session) { | ||||
|     _sessionStream.add(session); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<AuthenticationSession<Data>> currentSession() => sessionStream().last; | ||||
| 
 | ||||
|   @override | ||||
|   Stream<AuthenticationSession<Data>> sessionStream() => | ||||
|       _sessionStream.stream.asBroadcastStream(); | ||||
| } | ||||
| @ -0,0 +1,18 @@ | ||||
| // Copyright (C) 2023 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 'authentication_firebase_cache_data_source_impl.dart'; | ||||
| export 'authentication_session_data_source_impl.dart'; | ||||
| @ -23,55 +23,27 @@ import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; | ||||
| import 'package:wyatt_authentication_bloc/src/data/models/models.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/auth_session.dart'; | ||||
| import 'package:wyatt_authentication_bloc/src/domain/entities/authentication_change_event/authentication_change_event.dart'; | ||||
| import 'package:wyatt_type_utils/wyatt_type_utils.dart'; | ||||
| 
 | ||||
| /// {@template authentication_firebase_data_source_impl} | ||||
| /// Implementation of [AuthenticationRemoteDataSource] using Firebase. | ||||
| /// {@endtemplate} | ||||
| class AuthenticationFirebaseDataSourceImpl<Data> | ||||
|     extends AuthenticationRemoteDataSource<Data> { | ||||
|   /// {@macro authentication_firebase_data_source_impl} | ||||
|   AuthenticationFirebaseDataSourceImpl({ | ||||
|     FirebaseAuth? firebaseAuth, | ||||
|     GoogleSignIn? googleSignIn, | ||||
|   })  : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance, | ||||
|         _googleSignIn = googleSignIn ?? GoogleSignIn() { | ||||
|     _latestCredentials = BehaviorSubject(); | ||||
|     _sessionStream = BehaviorSubject(); | ||||
| 
 | ||||
|     // Check for account in memory (persistence) | ||||
|     _checkForCachedAccount(); | ||||
|   } | ||||
| 
 | ||||
|   late StreamController<AuthenticationSession<Data>> _sessionStream; | ||||
|   late StreamController<UserCredential?> _latestCredentials; | ||||
| 
 | ||||
|   final FirebaseAuth _firebaseAuth; | ||||
|   final GoogleSignIn _googleSignIn; | ||||
| 
 | ||||
|   Future<void> _checkForCachedAccount() async { | ||||
|     final currentUser = _firebaseAuth.currentUser; | ||||
| 
 | ||||
|     if (currentUser == null) { | ||||
|       _sessionStream.add( | ||||
|         const AuthenticationSession( | ||||
|           latestEvent: UnknownAuthenticationEvent(), | ||||
|         ), | ||||
|       ); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     final jwt = await currentUser.getIdToken(true); | ||||
|     final currentAccount = AccountModel.fromFirebaseUser( | ||||
|       currentUser, | ||||
|       accessToken: jwt, | ||||
|     ); | ||||
|     _sessionStream.add( | ||||
|       AuthenticationSession.fromEvent( | ||||
|         SignedInFromCacheEvent(account: currentAccount), | ||||
|       ), | ||||
|     ); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   Future<Account> _addToCredentialStream( | ||||
|     UserCredential userCredential, | ||||
|   ) async { | ||||
| @ -87,23 +59,6 @@ class AuthenticationFirebaseDataSourceImpl<Data> | ||||
|     return account; | ||||
|   } | ||||
| 
 | ||||
|   // Session related methods =================================================== | ||||
| 
 | ||||
|   /// {@macro add_session} | ||||
|   @override | ||||
|   void addSession(AuthenticationSession<Data> session) { | ||||
|     _sessionStream.add(session); | ||||
|   } | ||||
| 
 | ||||
|   /// {@macro session_stream} | ||||
|   @override | ||||
|   Stream<AuthenticationSession<Data>> sessionStream() => | ||||
|       _sessionStream.stream.asBroadcastStream(); | ||||
| 
 | ||||
|   /// {@macro current_session} | ||||
|   @override | ||||
|   Future<AuthenticationSession<Data>> currentSession() => sessionStream().last; | ||||
| 
 | ||||
|   // SignUp/SignIn methods ==================================================== | ||||
| 
 | ||||
|   /// {@macro signup_pwd} | ||||
|  | ||||
| @ -0,0 +1,17 @@ | ||||
| // Copyright (C) 2023 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 'authentication_firebase_data_source_impl.dart'; | ||||
| @ -16,17 +16,22 @@ | ||||
| 
 | ||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||
| import 'package:wyatt_authentication_bloc/src/core/utils/forms.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/auth_session.dart'; | ||||
| import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; | ||||
| import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_cache_data_source.dart'; | ||||
| import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_session_data_source.dart'; | ||||
| import 'package:wyatt_authentication_bloc/src/domain/domain.dart'; | ||||
| import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; | ||||
| import 'package:wyatt_type_utils/wyatt_type_utils.dart'; | ||||
| 
 | ||||
| /// {@template authentication_repository_impl} | ||||
| /// The default implementation of [AuthenticationRepository]. | ||||
| /// {@endtemplate} | ||||
| class AuthenticationRepositoryImpl<Data extends Object> | ||||
|     extends AuthenticationRepository<Data> { | ||||
|   /// {@macro authentication_repository_impl} | ||||
|   AuthenticationRepositoryImpl({ | ||||
|     required this.authenticationRemoteDataSource, | ||||
|     required this.authenticationCacheDataSource, | ||||
|     required this.authenticationSessionDataSource, | ||||
|     FormRepository? formRepository, | ||||
|     // ignore: strict_raw_type | ||||
|     List<FormInput>? extraSignUpInputs, | ||||
| @ -66,24 +71,57 @@ class AuthenticationRepositoryImpl<Data extends Object> | ||||
|       ); | ||||
|   } | ||||
| 
 | ||||
|   /// The remote data source used to perform the authentication process. | ||||
|   final AuthenticationRemoteDataSource<Data> authenticationRemoteDataSource; | ||||
| 
 | ||||
|   /// The cache data source used to cache the current account. | ||||
|   final AuthenticationCacheDataSource<Data> authenticationCacheDataSource; | ||||
| 
 | ||||
|   /// The session data source used to manage the current session. | ||||
|   final AuthenticationSessionDataSource<Data> authenticationSessionDataSource; | ||||
| 
 | ||||
|   late FormRepository _formRepository; | ||||
| 
 | ||||
|   /// {@macro form_repo} | ||||
|   @override | ||||
|   FormRepository get formRepository => _formRepository; | ||||
| 
 | ||||
|   // Cache related methods ==================================================== | ||||
| 
 | ||||
|   /// {@macro check_cache_account} | ||||
|   @override | ||||
|   Future<void> checkForCachedAccount() async { | ||||
|     final cachedAccount = | ||||
|         await authenticationCacheDataSource.getCachedAccount(); | ||||
| 
 | ||||
|     if (cachedAccount == null) { | ||||
|       addSession( | ||||
|         const AuthenticationSession( | ||||
|           latestEvent: UnknownAuthenticationEvent(), | ||||
|         ), | ||||
|       ); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     addSession( | ||||
|       AuthenticationSession.fromEvent( | ||||
|         SignedInFromCacheEvent(account: cachedAccount), | ||||
|       ), | ||||
|     ); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   // Session related methods =================================================== | ||||
| 
 | ||||
|   /// {@macro add_session} | ||||
|   @override | ||||
|   void addSession(AuthenticationSession<Data> session) => | ||||
|       authenticationRemoteDataSource.addSession(session); | ||||
|       authenticationSessionDataSource.addSession(session); | ||||
| 
 | ||||
|   /// {@macro session_stream} | ||||
|   @override | ||||
|   Stream<AuthenticationSession<Data>> sessionStream() => | ||||
|       authenticationRemoteDataSource.sessionStream(); | ||||
|       authenticationSessionDataSource.sessionStream(); | ||||
| 
 | ||||
|   /// {@macro current_session} | ||||
|   @override | ||||
| @ -91,7 +129,9 @@ class AuthenticationRepositoryImpl<Data extends Object> | ||||
|       Result.tryCatchAsync<AuthenticationSession<Data>, AppException, | ||||
|           AppException>( | ||||
|         () async { | ||||
|           final session = await authenticationRemoteDataSource.currentSession(); | ||||
|           final session = | ||||
|               await authenticationSessionDataSource.currentSession(); | ||||
| 
 | ||||
|           return session; | ||||
|         }, | ||||
|         (error) => error, | ||||
|  | ||||
| @ -14,4 +14,5 @@ | ||||
| // 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 'remote/authentication_remote_data_source.dart'; | ||||
| export 'local/local.dart'; | ||||
| export 'remote/remote.dart'; | ||||
|  | ||||
| @ -0,0 +1,40 @@ | ||||
| // Copyright (C) 2023 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_architecture/wyatt_architecture.dart'; | ||||
| import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; | ||||
| 
 | ||||
| /// {@template authentication_cache_data_source} | ||||
| /// A data source that manages the cache strategy. | ||||
| /// {@endtemplate} | ||||
| abstract class AuthenticationCacheDataSource<Data> extends BaseLocalDataSource { | ||||
|   /// {@macro authentication_cache_data_source} | ||||
|   const AuthenticationCacheDataSource(); | ||||
| 
 | ||||
|   /// Returns the cached account if it exists. | ||||
|   Future<Account?> getCachedAccount(); | ||||
| 
 | ||||
|   /// Adds the current account to the cache. | ||||
|   /// | ||||
|   /// If an account is already cached, it will be replaced. | ||||
|   Future<void> cacheAccount(Account account); | ||||
| 
 | ||||
|   /// Removes the current account from the cache. | ||||
|   /// | ||||
|   /// The cache will be empty after this operation. | ||||
|   /// If no account is cached, nothing will happen. | ||||
|   Future<void> removeCachedAccount(); | ||||
| } | ||||
| @ -0,0 +1,36 @@ | ||||
| // Copyright (C) 2023 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_architecture/wyatt_architecture.dart'; | ||||
| import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; | ||||
| 
 | ||||
| /// {@template authentication_session_data_source} | ||||
| /// A data source that manages the current session. | ||||
| /// {@endtemplate} | ||||
| abstract class AuthenticationSessionDataSource<Data> | ||||
|     extends BaseLocalDataSource { | ||||
|   /// {@macro authentication_session_data_source} | ||||
|   const AuthenticationSessionDataSource(); | ||||
| 
 | ||||
|   /// Adds a new session to the data source. | ||||
|   void addSession(AuthenticationSession<Data> session); | ||||
| 
 | ||||
|   /// Returns a stream of sessions. | ||||
|   Stream<AuthenticationSession<Data>> sessionStream(); | ||||
| 
 | ||||
|   /// Returns the current session. | ||||
|   Future<AuthenticationSession<Data>> currentSession(); | ||||
| } | ||||
| @ -0,0 +1,18 @@ | ||||
| // Copyright (C) 2023 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 'authentication_cache_data_source.dart'; | ||||
| export 'authentication_session_data_source.dart'; | ||||
| @ -16,49 +16,71 @@ | ||||
| 
 | ||||
| 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/auth_session.dart'; | ||||
| 
 | ||||
| /// Is responsible for abstracting the provenance of the data. | ||||
| /// {@template authentication_remote_data_source} | ||||
| /// A remote data source for authentication. | ||||
| /// It is responsible for all the external communication with the authentication | ||||
| /// providers. | ||||
| /// {@endtemplate} | ||||
| abstract class AuthenticationRemoteDataSource<Data> | ||||
|     extends BaseRemoteDataSource { | ||||
|   // Session related methods =================================================== | ||||
| 
 | ||||
|   void addSession(AuthenticationSession<Data> session); | ||||
|   Stream<AuthenticationSession<Data>> sessionStream(); | ||||
|   Future<AuthenticationSession<Data>> currentSession(); | ||||
|   /// {@macro authentication_remote_data_source} | ||||
|   const AuthenticationRemoteDataSource(); | ||||
| 
 | ||||
|   // SignUp/SignIn methods ==================================================== | ||||
| 
 | ||||
|   /// Sign up with email and password. | ||||
|   Future<Account> signUpWithEmailAndPassword({ | ||||
|     required String email, | ||||
|     required String password, | ||||
|   }); | ||||
| 
 | ||||
|   /// Sign in with email and password. | ||||
|   Future<Account> signInWithEmailAndPassword({ | ||||
|     required String email, | ||||
|     required String password, | ||||
|   }); | ||||
| 
 | ||||
|   /// Sign in anonymously. | ||||
|   Future<Account> signInAnonymously(); | ||||
| 
 | ||||
|   /// Sign in with Google. | ||||
|   Future<Account> signInWithGoogle(); | ||||
| 
 | ||||
|   /// Sign out. | ||||
|   Future<void> signOut(); | ||||
| 
 | ||||
|   // Account management methods =============================================== | ||||
|    | ||||
|   // Future<void> linkCurrentUserWith(AuthenticationProvider anotherProvider); | ||||
| 
 | ||||
|   /// Refresh the current account. | ||||
|   Future<Account> refresh(); | ||||
| 
 | ||||
|   /// Reauthenticate the current account. | ||||
|   Future<Account> reauthenticate(); | ||||
| 
 | ||||
|   /// Update the current account's email. | ||||
|   Future<Account> updateEmail({required String email}); | ||||
| 
 | ||||
|   /// Update the current account's password. | ||||
|   Future<Account> updatePassword({required String password}); | ||||
| 
 | ||||
|   /// Delete the current account. | ||||
|   Future<void> delete(); | ||||
| 
 | ||||
|   // Email related stuff ====================================================== | ||||
| 
 | ||||
|   /// Send an email verification. | ||||
|   Future<void> sendEmailVerification(); | ||||
| 
 | ||||
|   /// Send a password reset email. | ||||
|   Future<void> sendPasswordResetEmail({required String email}); | ||||
| 
 | ||||
|   /// Confirm password reset. | ||||
|   Future<void> confirmPasswordReset({ | ||||
|     required String code, | ||||
|     required String newPassword, | ||||
|   }); | ||||
| 
 | ||||
|   /// Verify password reset code. | ||||
|   Future<bool> verifyPasswordResetCode({required String code}); | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,17 @@ | ||||
| // Copyright (C) 2023 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 'authentication_remote_data_source.dart'; | ||||
| @ -19,13 +19,25 @@ import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; | ||||
| import 'package:wyatt_authentication_bloc/src/domain/entities/auth_session.dart'; | ||||
| import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; | ||||
| 
 | ||||
| /// {@template auth_repo} | ||||
| /// Authentication repository interface. | ||||
| /// {@endtemplate} | ||||
| abstract class AuthenticationRepository<Data> extends BaseRepository { | ||||
|   /// {@template form_repo} | ||||
|   /// Form repository used in different authentication cubits/blocs | ||||
|   /// {@endtemplate} | ||||
|   FormRepository get formRepository; | ||||
| 
 | ||||
|   // Stream related methods =================================================== | ||||
|   // Cache related methods ==================================================== | ||||
| 
 | ||||
|   /// {@template check_cache_account} | ||||
|   /// Checks if there is a cached account. | ||||
|   /// And if there is, it will sign in the user automatically by | ||||
|   /// emitting an event. | ||||
|   /// {@endtemplate} | ||||
|   Future<void> checkForCachedAccount(); | ||||
| 
 | ||||
|   // Session related methods =================================================== | ||||
| 
 | ||||
|   /// {@template add_session} | ||||
|   /// Add a new authentication event. | ||||
|  | ||||
| @ -27,27 +27,45 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart'; | ||||
| 
 | ||||
| part 'authentication_state.dart'; | ||||
| 
 | ||||
| /// {@template authentication_cubit} | ||||
| /// Abstract authentication cubit class needs to be implemented in application. | ||||
| /// | ||||
| /// This cubit is in charge of managing the global authentication state of | ||||
| /// the application. | ||||
| /// | ||||
| /// Its here you can override every callbacks and add your custom logic. | ||||
| /// {@endtemplate} | ||||
| abstract class AuthenticationCubit<Data> | ||||
|     extends Cubit<AuthenticationState<Data>> { | ||||
|   /// {@macro authentication_cubit} | ||||
|   AuthenticationCubit({ | ||||
|     required this.authenticationRepository, | ||||
|   }) : super(const AuthenticationState.unknown()) { | ||||
|     _listenForAuthenticationChanges(); | ||||
|     _init(); | ||||
|   } | ||||
| 
 | ||||
|   /// The authentication repository. | ||||
|   final AuthenticationRepository<Data> authenticationRepository; | ||||
| 
 | ||||
|   /// The latest session. | ||||
|   AuthenticationSession<Data>? _latestSession; | ||||
| 
 | ||||
|   /// Method that is called when the cubit is initialized. | ||||
|   Future<void> _init() async { | ||||
|     /// Setup listeners. | ||||
|     _listenForAuthenticationChanges(); | ||||
| 
 | ||||
|     /// Check if there is a cached account. | ||||
|     await authenticationRepository.checkForCachedAccount(); | ||||
|   } | ||||
| 
 | ||||
|   void _listenForAuthenticationChanges() { | ||||
|     authenticationRepository.sessionStream().asyncMap((session) async { | ||||
|       final event = session.latestEvent; | ||||
| 
 | ||||
|       /// If the session is signed in from cache. | ||||
|       if (event is SignedInFromCacheEvent) { | ||||
|         /// Call the custom routine. | ||||
|         final customRoutineResult = await onSignInFromCache(session); | ||||
| 
 | ||||
|         if (customRoutineResult.isOk) { | ||||
| @ -64,12 +82,18 @@ abstract class AuthenticationCubit<Data> | ||||
|       } | ||||
|       return session; | ||||
|     }).listen((session) async { | ||||
|       /// Save the latest session. | ||||
|       _latestSession = session; | ||||
| 
 | ||||
|       /// If there is an account: emit authenticated state. | ||||
|       if (session.account != null) { | ||||
|         emit(AuthenticationState<Data>.authenticated(session)); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       /// If there is no account: emit unauthenticated state. | ||||
|       emit(AuthenticationState<Data>.unauthenticated()); | ||||
| 
 | ||||
|       return; | ||||
|     }); | ||||
|   } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user