diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart index a0344195..5bc23a2d 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +import 'dart:async'; + +import 'package:rxdart/subjects.dart'; import 'package:wyatt_authentication_bloc/src/data/models/account_model_firebase.dart'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; @@ -24,7 +27,17 @@ class AuthenticationFirebaseDataSourceImpl FirebaseAuth? firebaseAuth, GoogleSignIn? googleSignIn, }) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance, - _googleSignIn = googleSignIn ?? GoogleSignIn(); + _googleSignIn = googleSignIn ?? GoogleSignIn() { + // _accountStream = StreamController(); + _accountStream = BehaviorSubject(); + // Check for account in memory (persistence) + final currentAccount = (_firebaseAuth.currentUser != null) + ? AccountModelFirebase.fromFirebaseUser(_firebaseAuth.currentUser) + : null; + _accountStream.add(currentAccount); + } + + late StreamController _accountStream; final FirebaseAuth _firebaseAuth; final GoogleSignIn _googleSignIn; @@ -41,8 +54,10 @@ class AuthenticationFirebaseDataSourceImpl password: password, ); _latestCreds = userCredential; - final user = userCredential.user; - return AccountModelFirebase.fromFirebaseUser(user); + final account = + AccountModelFirebase.fromFirebaseUserCredential(userCredential); + _accountStream.add(account); + return account; } on FirebaseAuthException catch (e) { throw SignInWithEmailAndPasswordFailureFirebase.fromCode(e.code); } catch (_) { @@ -50,9 +65,8 @@ class AuthenticationFirebaseDataSourceImpl } } - @override - /// {@macro signup} + @override Future signUp({ required String email, required String password, @@ -63,8 +77,10 @@ class AuthenticationFirebaseDataSourceImpl password: password, ); _latestCreds = userCredential; - final user = userCredential.user; - return AccountModelFirebase.fromFirebaseUser(user); + final account = + AccountModelFirebase.fromFirebaseUserCredential(userCredential); + _accountStream.add(account); + return account; } on FirebaseAuthException catch (e) { throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(e.code); } catch (_) { @@ -77,6 +93,7 @@ class AuthenticationFirebaseDataSourceImpl try { _latestCreds = null; await _firebaseAuth.signOut(); + _accountStream.add(null); } catch (_) { throw SignOutFailureFirebase(); } @@ -99,17 +116,7 @@ class AuthenticationFirebaseDataSourceImpl } @override - Stream streamAccount() => - _firebaseAuth.userChanges().map((user) { - if (user.isNull) { - return null; - } - try { - return AccountModelFirebase.fromFirebaseUser(user); - } on Exception { - return null; - } - }); + Stream streamAccount() => _accountStream.stream.asBroadcastStream(); @override Future confirmPasswordReset({ @@ -155,8 +162,10 @@ class AuthenticationFirebaseDataSourceImpl try { final userCredential = await _firebaseAuth.signInAnonymously(); _latestCreds = userCredential; - final user = userCredential.user; - return AccountModelFirebase.fromFirebaseUser(user); + final account = + AccountModelFirebase.fromFirebaseUserCredential(userCredential); + _accountStream.add(account); + return account; } on FirebaseAuthException catch (e) { throw SignInAnonymouslyFailureFirebase.fromCode(e.code); } catch (_) { @@ -184,8 +193,10 @@ class AuthenticationFirebaseDataSourceImpl await _firebaseAuth.signInWithCredential(credential); _latestCreds = userCredential; - final user = userCredential.user; - return AccountModelFirebase.fromFirebaseUser(user); + final account = + AccountModelFirebase.fromFirebaseUserCredential(userCredential); + _accountStream.add(account); + return account; } on FirebaseAuthException catch (e) { throw SignInWithGoogleFailureFirebase.fromCode(e.code); } catch (_) { @@ -209,6 +220,9 @@ class AuthenticationFirebaseDataSourceImpl Future refresh() async { try { await _firebaseAuth.currentUser!.reload(); + final account = + AccountModelFirebase.fromFirebaseUser(_firebaseAuth.currentUser); + _accountStream.add(account); } on FirebaseAuthException catch (e) { throw RefreshFailureFirebase.fromCode(e.code); } catch (_) { @@ -225,8 +239,10 @@ class AuthenticationFirebaseDataSourceImpl } else { throw Exception(); // Get caught just after. } - final user = _firebaseAuth.currentUser; - return AccountModelFirebase.fromFirebaseUser(user); + final account = + AccountModelFirebase.fromFirebaseUser(_firebaseAuth.currentUser); + _accountStream.add(account); + return account; } on FirebaseAuthException catch (e) { throw ReauthenticateFailureFirebase.fromCode(e.code); } catch (_) { @@ -238,8 +254,10 @@ class AuthenticationFirebaseDataSourceImpl Future updateEmail({required String email}) async { try { await _firebaseAuth.currentUser!.updateEmail(email); - final user = _firebaseAuth.currentUser; - return AccountModelFirebase.fromFirebaseUser(user); + final account = + AccountModelFirebase.fromFirebaseUser(_firebaseAuth.currentUser); + _accountStream.add(account); + return account; } on FirebaseAuthException catch (e) { throw UpdateEmailFailureFirebase.fromCode(e.code); } catch (_) { @@ -251,8 +269,10 @@ class AuthenticationFirebaseDataSourceImpl Future updatePassword({required String password}) async { try { await _firebaseAuth.currentUser!.updatePassword(password); - final user = _firebaseAuth.currentUser; - return AccountModelFirebase.fromFirebaseUser(user); + final account = + AccountModelFirebase.fromFirebaseUser(_firebaseAuth.currentUser); + _accountStream.add(account); + return account; } on FirebaseAuthException catch (e) { throw UpdatePasswordFailureFirebase.fromCode(e.code); } catch (_) { diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/account_model_firebase.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/account_model_firebase.dart index d6a70ba5..07e5b5a0 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/models/account_model_firebase.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/models/account_model_firebase.dart @@ -15,7 +15,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; +import 'package:wyatt_authentication_bloc/src/data/models/account_model.dart'; class AccountModelFirebase extends AccountModel { AccountModelFirebase._({ @@ -42,16 +44,37 @@ class AccountModelFirebase extends AccountModel { providerId: providerId, creationTime: user.metadata.creationTime, lastSignInTime: user.metadata.lastSignInTime, - isNewUser: (user.metadata.creationTime != null && - user.metadata.lastSignInTime != null) - ? user.metadata.lastSignInTime! == user.metadata.creationTime! - : null, + isNewUser: false, email: user.email, phoneNumber: user.phoneNumber, photoURL: user.photoURL, ); } else { - throw ModelParsingFailureFirebase('null-user', 'User cannot be null!'); + throw ModelParsingFailureFirebase('null-user', 'User cannot be null'); + } + } + + factory AccountModelFirebase.fromFirebaseUserCredential( + UserCredential? userCredential, + ) { + final user = userCredential?.user; + if (user != null) { + final providerId = + (user.providerData.isEmpty) ? '' : user.providerData.first.providerId; + return AccountModelFirebase._( + uid: user.uid, + emailVerified: user.emailVerified, + isAnonymous: user.isAnonymous, + providerId: providerId, + creationTime: user.metadata.creationTime, + lastSignInTime: user.metadata.lastSignInTime, + isNewUser: userCredential?.additionalUserInfo?.isNewUser, + email: user.email, + phoneNumber: user.phoneNumber, + photoURL: user.photoURL, + ); + } else { + throw ModelParsingFailureFirebase('null-user', 'User cannot be null'); } } }