refactor(authentication): use custom user changes stream

This commit is contained in:
Hugo Pointcheval 2022-12-30 16:15:34 +01:00
parent 7f0544d19c
commit 830d32152b
Signed by: hugo
GPG Key ID: 3AAC487E131E00BC
2 changed files with 77 additions and 34 deletions

View File

@ -14,6 +14,9 @@
// 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/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<Account?> _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<Account> 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<Account?> streamAccount() =>
_firebaseAuth.userChanges().map<Account?>((user) {
if (user.isNull) {
return null;
}
try {
return AccountModelFirebase.fromFirebaseUser(user);
} on Exception {
return null;
}
});
Stream<Account?> streamAccount() => _accountStream.stream.asBroadcastStream();
@override
Future<void> 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<void> 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<Account> 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<Account> 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 (_) {

View File

@ -15,7 +15,9 @@
// 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/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');
}
}
}