diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_firebase.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_firebase.dart
deleted file mode 100644
index 0cf6d5dc..00000000
--- a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_firebase.dart
+++ /dev/null
@@ -1,338 +0,0 @@
-// 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 .
-
-import 'dart:async';
-
-import 'package:firebase_auth/firebase_auth.dart';
-import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
-import 'package:google_sign_in/google_sign_in.dart';
-import 'package:sign_in_with_apple/sign_in_with_apple.dart';
-import 'package:twitter_login/twitter_login.dart';
-import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart';
-import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions_firebase.dart';
-import 'package:wyatt_authentication_bloc/src/core/extensions/firebase_auth_user_x.dart';
-import 'package:wyatt_authentication_bloc/src/core/utils/cryptography.dart';
-import 'package:wyatt_authentication_bloc/src/data/models/user_firebase.dart';
-import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart'
- as wyatt;
-import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart';
-
-class AuthenticationRepositoryFirebase implements AuthenticationRepository {
- final _controller = StreamController();
- final FirebaseAuth _firebaseAuth;
- final TwitterLogin? _twitterLogin;
-
- UserFirebase _userCache = const UserFirebase.empty();
-
- AuthenticationRepositoryFirebase({
- FirebaseAuth? firebaseAuth,
- TwitterLogin? twitterLogin,
- }) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance,
- _twitterLogin = twitterLogin {
- _controller.sink.add(AuthCubitStatus.stoped);
- }
-
- @override
- Stream get cubitStatus =>
- _controller.stream.asBroadcastStream();
-
- @override
- void changeCubitStatus(AuthCubitStatus status) =>
- _controller.sink.add(status);
-
- @override
- Stream get user =>
- _firebaseAuth.userChanges().map((firebaseUser) {
- final UserFirebase user = (firebaseUser == null)
- ? const UserFirebase.empty()
- : firebaseUser.model;
- _userCache = user;
- return user;
- });
-
- @override
- wyatt.User get currentUser => _userCache;
-
- @override
- Future applyActionCode(String code) async {
- try {
- await _firebaseAuth.applyActionCode(code);
- } on FirebaseAuthException catch (e) {
- throw ApplyActionCodeFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw ApplyActionCodeFailureFirebase();
- }
- }
-
- @override
- Future signUp({
- required String email,
- required String password,
- }) async {
- try {
- final creds = await _firebaseAuth.createUserWithEmailAndPassword(
- email: email,
- password: password,
- );
- return creds.user?.uid;
- } on FirebaseAuthException catch (e) {
- throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw SignUpWithEmailAndPasswordFailureFirebase();
- }
- }
-
- @override
- Future> fetchSignInMethodsForEmail({
- required String email,
- }) async {
- try {
- return await _firebaseAuth.fetchSignInMethodsForEmail(email);
- } on FirebaseAuthException catch (e) {
- throw FetchSignInMethodsForEmailFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw FetchSignInMethodsForEmailFailureFirebase();
- }
- }
-
- @override
- Future signInAnonymously() async {
- try {
- await _firebaseAuth.signInAnonymously();
- } on FirebaseAuthException catch (e) {
- throw SignInAnonymouslyFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw SignInAnonymouslyFailureFirebase();
- }
- }
-
- @override
- Future signInWithGoogle() async {
- // Trigger the authentication flow
- final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
-
- // Obtain the auth details from the request
- final GoogleSignInAuthentication? googleAuth =
- await googleUser?.authentication;
-
- // Create a new credential
- final credential = GoogleAuthProvider.credential(
- accessToken: googleAuth?.accessToken,
- idToken: googleAuth?.idToken,
- );
-
- try {
- await _firebaseAuth.signInWithCredential(credential);
- } on FirebaseAuthException catch (e) {
- throw SignInWithGoogleFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw SignInWithGoogleFailureFirebase();
- }
- }
-
- @override
- Future signInWithFacebook() async {
- // Trigger the sign-in flow
- final LoginResult loginResult = await FacebookAuth.instance.login();
-
- // Create a credential from the access token
- final OAuthCredential credential =
- FacebookAuthProvider.credential(loginResult.accessToken?.token ?? '');
-
- try {
- await _firebaseAuth.signInWithCredential(credential);
- } on FirebaseAuthException catch (e) {
- throw SignInWithFacebookFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw SignInWithFacebookFailureFirebase();
- }
- }
-
- @override
- Future signInWithApple() async {
- // To prevent replay attacks with the credential returned from Apple, we
- // include a nonce in the credential request. When signing in with
- // Firebase, the nonce in the id token returned by Apple, is expected to
- // match the sha256 hash of `rawNonce`.
- final rawNonce = Cryptography.generateNonce();
- final nonce = Cryptography.sha256ofString(rawNonce);
-
- // Request credential for the currently signed in Apple account.
- final appleCredential = await SignInWithApple.getAppleIDCredential(
- scopes: [
- AppleIDAuthorizationScopes.email,
- AppleIDAuthorizationScopes.fullName,
- ],
- nonce: nonce,
- );
-
- // Create an `OAuthCredential` from the credential returned by Apple.
- final credential = OAuthProvider('apple.com').credential(
- idToken: appleCredential.identityToken,
- rawNonce: rawNonce,
- );
-
- // Sign in the user with Firebase. If the nonce we generated earlier does
- // not match the nonce in `appleCredential.identityToken`,
- // sign in will fail.
- try {
- await _firebaseAuth.signInWithCredential(credential);
- } on FirebaseAuthException catch (e) {
- throw SignInWithAppleFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw SignInWithAppleFailureFirebase();
- }
- }
-
- @override
- Future signInWithTwitter() async {
- final twitterLogin = _twitterLogin;
- if (twitterLogin == null) {
- throw SignInWithTwitterFailureFirebase();
- }
-
- // Trigger the sign-in flow
- final authResult = await twitterLogin.login();
-
- // Create a credential from the access token
- final credential = TwitterAuthProvider.credential(
- accessToken: authResult.authToken!,
- secret: authResult.authTokenSecret!,
- );
-
- try {
- await _firebaseAuth.signInWithCredential(credential);
- } on FirebaseAuthException catch (e) {
- throw SignInWithCredentialFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw SignInWithCredentialFailureFirebase();
- }
- }
-
- @override
- Future signInWithEmailLink(String email, String emailLink) async {
- try {
- await _firebaseAuth.signInWithEmailLink(
- email: email,
- emailLink: emailLink,
- );
- } on FirebaseAuthException catch (e) {
- throw SignInWithEmailLinkFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw SignInWithEmailLinkFailureFirebase();
- }
- }
-
- @override
- Future signInWithEmailAndPassword({
- required String email,
- required String password,
- }) async {
- try {
- await _firebaseAuth.signInWithEmailAndPassword(
- email: email,
- password: password,
- );
- } on FirebaseAuthException catch (e) {
- throw SignInWithEmailAndPasswordFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw SignInWithEmailAndPasswordFailureFirebase();
- }
- }
-
- @override
- Future sendEmailVerification() async {
- try {
- await _userCache.inner!.sendEmailVerification();
- } catch (e) {
- throw SendEmailVerificationFailureFirebase();
- }
- }
-
- @override
- Future sendPasswordResetEmail({required String email}) async {
- try {
- await _firebaseAuth.sendPasswordResetEmail(email: email);
- } on FirebaseAuthException catch (e) {
- throw SendPasswordResetEmailFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw SendPasswordResetEmailFailureFirebase();
- }
- }
-
- @override
- Future sendSignInLinkEmail({required String email}) async {
- try {
- // TODO(hpcl): implement sendSignInLinkEmail
- } on FirebaseAuthException catch (e) {
- throw SendSignInLinkEmailFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw SendSignInLinkEmailFailureFirebase();
- }
- }
-
- @override
- Future confirmPasswordReset({
- required String code,
- required String newPassword,
- }) async {
- try {
- await _firebaseAuth.confirmPasswordReset(
- code: code,
- newPassword: newPassword,
- );
- } on FirebaseAuthException catch (e) {
- throw ConfirmPasswordResetFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw ConfirmPasswordResetFailureFirebase();
- }
- throw UnimplementedError();
- }
-
- @override
- Future verifyPasswordResetCode({required String code}) async {
- try {
- await _firebaseAuth.verifyPasswordResetCode(code);
- } on FirebaseAuthException catch (e) {
- throw VerifyPasswordResetCodeFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw VerifyPasswordResetCodeFailureFirebase();
- }
- }
-
- @override
- Future signOut() async {
- try {
- await Future.wait([
- _firebaseAuth.signOut(),
- ]);
- _userCache = const UserFirebase.empty();
- } catch (_) {
- throw SignOutFailureFirebase();
- }
- }
-
- @override
- Future refresh() async {
- try {
- await _userCache.inner!.reload();
- } on FirebaseAuthException catch (e) {
- throw RefreshFailureFirebase.fromCode(e.code);
- } catch (_) {
- throw RefreshFailureFirebase();
- }
- }
-}
diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart
new file mode 100644
index 00000000..e5526ea8
--- /dev/null
+++ b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart
@@ -0,0 +1,156 @@
+// 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 .
+
+import 'package:wyatt_architecture/wyatt_architecture.dart';
+import 'package:wyatt_authentication_bloc/src/data/models/account_wrapper_model.dart';
+import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_local_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_wrapper.dart';
+import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart';
+import 'package:wyatt_type_utils/wyatt_type_utils.dart';
+
+class AuthenticationRepositoryImpl
+ extends AuthenticationRepository {
+ final AuthenticationLocalDataSource _authenticationLocalDataSource;
+ final AuthenticationRemoteDataSource _authenticationRemoteDataSource;
+
+ final FutureResult Function(Account? account)? _onSignUpSuccess;
+ final FutureResult Function(Account? account)? _onAccountChanges;
+
+ AuthenticationRepositoryImpl(
+ this._authenticationLocalDataSource,
+ this._authenticationRemoteDataSource,
+ this._onSignUpSuccess,
+ this._onAccountChanges,
+ );
+
+ @override
+ FutureResult signInWithEmailAndPassword({
+ required String email,
+ required String password,
+ }) =>
+ Result.tryCatchAsync(
+ () async {
+ final account =
+ await _authenticationRemoteDataSource.signInWithEmailAndPassword(
+ email: email,
+ password: password,
+ );
+ _authenticationLocalDataSource.storeAccount(account);
+ return account;
+ },
+ (error) => error,
+ );
+
+ @override
+ FutureResult signOut() =>
+ Result.tryCatchAsync(
+ () async {
+ await _authenticationRemoteDataSource.signOut();
+ _authenticationLocalDataSource.destroy();
+ },
+ (error) => error,
+ );
+
+ @override
+ FutureResult signUp({
+ required String email,
+ required String password,
+ }) =>
+ Result.tryCatchAsync(
+ () async {
+ final account = await _authenticationRemoteDataSource.signUp(
+ email: email,
+ password: password,
+ );
+ _authenticationLocalDataSource.storeAccount(account);
+ if (_onSignUpSuccess.isNotNull) {
+ final dataResult = await _onSignUpSuccess!.call(account);
+ dataResult.fold(
+ _authenticationLocalDataSource.storeData,
+ (error) => throw error,
+ );
+ }
+ return account;
+ },
+ (error) => error,
+ );
+
+ @override
+ Result destroyCache() =>
+ Result.tryCatch(
+ _authenticationLocalDataSource.destroy,
+ (error) => error,
+ );
+
+ @override
+ Result getAccount() =>
+ Result.tryCatch(
+ _authenticationLocalDataSource.loadAccount,
+ (error) => error,
+ );
+
+ @override
+ Result setAccount(
+ Account account,
+ ) =>
+ Result.tryCatch(
+ () {
+ _authenticationLocalDataSource.storeAccount(account);
+ return account;
+ },
+ (error) => error,
+ );
+
+ @override
+ Result getData() =>
+ Result.tryCatch(
+ _authenticationLocalDataSource.loadData,
+ (error) => error,
+ );
+
+ @override
+ Result setData(
+ T data,
+ ) =>
+ Result.tryCatch(
+ () {
+ _authenticationLocalDataSource.storeData(data);
+ return data;
+ },
+ (error) => error,
+ );
+
+ @override
+ FutureResult getIdentityToken() =>
+ Result.tryCatchAsync(
+ _authenticationRemoteDataSource.getIdentityToken,
+ (error) => error,
+ );
+
+ @override
+ Stream>> streamAccount() =>
+ _authenticationRemoteDataSource.streamAccount().map((account) async {
+ if (_onAccountChanges.isNotNull) {
+ final dataResult = await _onAccountChanges!.call(account);
+ return dataResult.map((data) => AccountWrapperModel(account, data));
+ }
+ return Ok, AppException>(
+ AccountWrapperModel(account, null),
+ );
+ });
+}
diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart
new file mode 100644
index 00000000..7858c9e7
--- /dev/null
+++ b/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart
@@ -0,0 +1,17 @@
+// 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 .
+
+export 'authentication_repository_impl.dart';
diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart
index 35c80a72..432b1de6 100644
--- a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart
+++ b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart
@@ -14,126 +14,34 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart';
-import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart';
-import 'package:wyatt_authentication_bloc/src/domain/entities/user.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_wrapper.dart';
+import 'package:wyatt_type_utils/wyatt_type_utils.dart';
-/// {@template authentication_repository}
-/// Repository which manages user authentication.
-/// {@endtemplate}
-abstract class AuthenticationRepository {
- /// Stream of [AuthCubitStatus] wich will emit the current cubit status.
- Stream get cubitStatus;
+abstract class AuthenticationRepository extends BaseRepository {
+ FutureResult signUp({
+ required String email,
+ required String password,
+
+ });
- /// Changes cubit status.(Useful to start or stop the engine.)
- void changeCubitStatus(AuthCubitStatus status);
-
- /// Stream of [User] which will emit the current user when
- /// the authentication state changes.
- ///
- /// Emits [User.empty] if the user is not authenticated.
- Stream get user;
-
- /// Returns the current cached account.
- /// Defaults to [User.empty] if there is no cached user.
- User get currentUser;
-
- /// Applies action code
- ///
- /// [code] - The action code sent to the user's email address.
- /// Throw [ApplyActionCodeFailureInterface] if an exception occurs.
- Future applyActionCode(String code);
-
- /// Creates a new user with the provided [email] and [password].
- ///
- /// Returns the newly created user's unique identifier.
- ///
- /// Throws a [SignUpWithEmailAndPasswordFailureInterface] if
- /// an exception occurs.
- Future signUp({required String email, required String password});
-
- /// Fetches sign in methods for [email].
- ///
- /// Throws a [FetchSignInMethodsForEmailFailureInterface] if
- /// an exception occurs.
- Future> fetchSignInMethodsForEmail({required String email});
-
- /// Sign in anonimously.
- ///
- /// Throws a [SignInAnonymouslyFailureInterface] if an exception occurs.
- Future signInAnonymously();
-
- /// Starts the Sign In with Google Flow.
- ///
- /// Throws a [SignInWithGoogleFailureInterface] if an exception occurs.
- Future signInWithGoogle();
-
- /// Starts the Sign In with Facebook Flow.
- ///
- /// Throws a [SignInWithFacebookFailureInterface] if an exception occurs.
- Future signInWithFacebook();
-
- /// Starts the Sign In with Apple Flow.
- ///
- /// Throws a [SignInWithAppleFailureInterface] if an exception occurs.
- Future signInWithApple();
-
- /// Starts the Sign In with Twitter Flow.
- ///
- /// Throws a [SignInWithTwitterFailureInterface] if an exception occurs.
- Future signInWithTwitter();
-
- /// Signs in using an email address and email sign-in link.
- ///
- /// Throws a [SignInWithEmailLinkFailureInterface] if an exception occurs.
- Future signInWithEmailLink(
- String email,
- String emailLink,
- );
-
- /// Signs in with the provided [email] and [password].
- ///
- /// Throws a [SignInWithEmailAndPasswordFailureInterface] if
- /// an exception occurs.
- Future signInWithEmailAndPassword({
+ FutureResult signInWithEmailAndPassword({
required String email,
required String password,
});
- /// Sends verification email to the provided [user].
- ///
- /// Throws a [SendEmailVerificationFailureInterface] if an exception occurs.
- Future sendEmailVerification();
+ FutureResult signOut();
- /// Sends a password reset email to the provided [email].
- ///
- /// Throws a [SendPasswordResetEmailFailureInterface] if an exception occurs.
- Future sendPasswordResetEmail({required String email});
+ Stream>> streamAccount();
- /// Sends link to login.
- ///
- /// Throws a [SendSignInLinkEmailFailureInterface] if an exception occurs.
- Future sendSignInLinkEmail({required String email});
+ FutureResult getIdentityToken();
- /// Confirms the password reset with the provided [newPassword] and [code].
- ///
- /// Throws a [ConfirmPasswordResetFailureInterface] if an exception occurs.
- Future confirmPasswordReset({
- required String code,
- required String newPassword,
- });
+ Result getAccount();
+ Result setAccount(Account account);
- /// Verify password reset code.
- ///
- /// Throws a [VerifyPasswordResetCodeFailureInterface] if an exception occurs.
- Future verifyPasswordResetCode({required String code});
+ Result getData();
+ Result setData(T data);
- /// Signs out the current user which will emit
- /// [User.empty] from the [user] Stream.
- Future signOut();
-
- /// Refreshes the current user.
- ///
- /// Throws a [RefreshFailureInterface] if an exception occurs.
- Future refresh();
+ Result destroyCache();
}
diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart
new file mode 100644
index 00000000..85f8ae88
--- /dev/null
+++ b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart
@@ -0,0 +1,17 @@
+// 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 .
+
+export 'authentication_repository.dart';