master #81
@ -14,4 +14,5 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// 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/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/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/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';
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
|
/// {@template authentication_firebase_data_source_impl}
|
||||||
|
/// Implementation of [AuthenticationRemoteDataSource] using Firebase.
|
||||||
|
/// {@endtemplate}
|
||||||
class AuthenticationFirebaseDataSourceImpl<Data>
|
class AuthenticationFirebaseDataSourceImpl<Data>
|
||||||
extends AuthenticationRemoteDataSource<Data> {
|
extends AuthenticationRemoteDataSource<Data> {
|
||||||
|
/// {@macro authentication_firebase_data_source_impl}
|
||||||
AuthenticationFirebaseDataSourceImpl({
|
AuthenticationFirebaseDataSourceImpl({
|
||||||
FirebaseAuth? firebaseAuth,
|
FirebaseAuth? firebaseAuth,
|
||||||
GoogleSignIn? googleSignIn,
|
GoogleSignIn? googleSignIn,
|
||||||
}) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance,
|
}) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance,
|
||||||
_googleSignIn = googleSignIn ?? GoogleSignIn() {
|
_googleSignIn = googleSignIn ?? GoogleSignIn() {
|
||||||
_latestCredentials = BehaviorSubject();
|
_latestCredentials = BehaviorSubject();
|
||||||
_sessionStream = BehaviorSubject();
|
|
||||||
|
|
||||||
// Check for account in memory (persistence)
|
|
||||||
_checkForCachedAccount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
late StreamController<AuthenticationSession<Data>> _sessionStream;
|
|
||||||
late StreamController<UserCredential?> _latestCredentials;
|
late StreamController<UserCredential?> _latestCredentials;
|
||||||
|
|
||||||
final FirebaseAuth _firebaseAuth;
|
final FirebaseAuth _firebaseAuth;
|
||||||
final GoogleSignIn _googleSignIn;
|
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(
|
Future<Account> _addToCredentialStream(
|
||||||
UserCredential userCredential,
|
UserCredential userCredential,
|
||||||
) async {
|
) async {
|
||||||
@ -87,23 +59,6 @@ class AuthenticationFirebaseDataSourceImpl<Data>
|
|||||||
return account;
|
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 ====================================================
|
// SignUp/SignIn methods ====================================================
|
||||||
|
|
||||||
/// {@macro signup_pwd}
|
/// {@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_architecture/wyatt_architecture.dart';
|
||||||
import 'package:wyatt_authentication_bloc/src/core/utils/forms.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/data_sources/local/authentication_cache_data_source.dart';
|
||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/account.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';
|
import 'package:wyatt_authentication_bloc/src/domain/domain.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';
|
||||||
|
|
||||||
|
/// {@template authentication_repository_impl}
|
||||||
|
/// The default implementation of [AuthenticationRepository].
|
||||||
|
/// {@endtemplate}
|
||||||
class AuthenticationRepositoryImpl<Data extends Object>
|
class AuthenticationRepositoryImpl<Data extends Object>
|
||||||
extends AuthenticationRepository<Data> {
|
extends AuthenticationRepository<Data> {
|
||||||
|
/// {@macro authentication_repository_impl}
|
||||||
AuthenticationRepositoryImpl({
|
AuthenticationRepositoryImpl({
|
||||||
required this.authenticationRemoteDataSource,
|
required this.authenticationRemoteDataSource,
|
||||||
|
required this.authenticationCacheDataSource,
|
||||||
|
required this.authenticationSessionDataSource,
|
||||||
FormRepository? formRepository,
|
FormRepository? formRepository,
|
||||||
// ignore: strict_raw_type
|
// ignore: strict_raw_type
|
||||||
List<FormInput>? extraSignUpInputs,
|
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;
|
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;
|
late FormRepository _formRepository;
|
||||||
|
|
||||||
/// {@macro form_repo}
|
/// {@macro form_repo}
|
||||||
@override
|
@override
|
||||||
FormRepository get formRepository => _formRepository;
|
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 ===================================================
|
// Session related methods ===================================================
|
||||||
|
|
||||||
/// {@macro add_session}
|
/// {@macro add_session}
|
||||||
@override
|
@override
|
||||||
void addSession(AuthenticationSession<Data> session) =>
|
void addSession(AuthenticationSession<Data> session) =>
|
||||||
authenticationRemoteDataSource.addSession(session);
|
authenticationSessionDataSource.addSession(session);
|
||||||
|
|
||||||
/// {@macro session_stream}
|
/// {@macro session_stream}
|
||||||
@override
|
@override
|
||||||
Stream<AuthenticationSession<Data>> sessionStream() =>
|
Stream<AuthenticationSession<Data>> sessionStream() =>
|
||||||
authenticationRemoteDataSource.sessionStream();
|
authenticationSessionDataSource.sessionStream();
|
||||||
|
|
||||||
/// {@macro current_session}
|
/// {@macro current_session}
|
||||||
@override
|
@override
|
||||||
@ -91,7 +129,9 @@ class AuthenticationRepositoryImpl<Data extends Object>
|
|||||||
Result.tryCatchAsync<AuthenticationSession<Data>, AppException,
|
Result.tryCatchAsync<AuthenticationSession<Data>, AppException,
|
||||||
AppException>(
|
AppException>(
|
||||||
() async {
|
() async {
|
||||||
final session = await authenticationRemoteDataSource.currentSession();
|
final session =
|
||||||
|
await authenticationSessionDataSource.currentSession();
|
||||||
|
|
||||||
return session;
|
return session;
|
||||||
},
|
},
|
||||||
(error) => error,
|
(error) => error,
|
||||||
|
@ -14,4 +14,5 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// 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_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/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>
|
abstract class AuthenticationRemoteDataSource<Data>
|
||||||
extends BaseRemoteDataSource {
|
extends BaseRemoteDataSource {
|
||||||
// Session related methods ===================================================
|
/// {@macro authentication_remote_data_source}
|
||||||
|
const AuthenticationRemoteDataSource();
|
||||||
void addSession(AuthenticationSession<Data> session);
|
|
||||||
Stream<AuthenticationSession<Data>> sessionStream();
|
|
||||||
Future<AuthenticationSession<Data>> currentSession();
|
|
||||||
|
|
||||||
// SignUp/SignIn methods ====================================================
|
// SignUp/SignIn methods ====================================================
|
||||||
|
|
||||||
|
/// Sign up with email and password.
|
||||||
Future<Account> signUpWithEmailAndPassword({
|
Future<Account> signUpWithEmailAndPassword({
|
||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Sign in with email and password.
|
||||||
Future<Account> signInWithEmailAndPassword({
|
Future<Account> signInWithEmailAndPassword({
|
||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Sign in anonymously.
|
||||||
Future<Account> signInAnonymously();
|
Future<Account> signInAnonymously();
|
||||||
|
|
||||||
|
/// Sign in with Google.
|
||||||
Future<Account> signInWithGoogle();
|
Future<Account> signInWithGoogle();
|
||||||
|
|
||||||
|
/// Sign out.
|
||||||
Future<void> signOut();
|
Future<void> signOut();
|
||||||
|
|
||||||
// Account management methods ===============================================
|
// Account management methods ===============================================
|
||||||
|
|
||||||
// Future<void> linkCurrentUserWith(AuthenticationProvider anotherProvider);
|
/// Refresh the current account.
|
||||||
Future<Account> refresh();
|
Future<Account> refresh();
|
||||||
|
|
||||||
|
/// Reauthenticate the current account.
|
||||||
Future<Account> reauthenticate();
|
Future<Account> reauthenticate();
|
||||||
|
|
||||||
|
/// Update the current account's email.
|
||||||
Future<Account> updateEmail({required String email});
|
Future<Account> updateEmail({required String email});
|
||||||
|
|
||||||
|
/// Update the current account's password.
|
||||||
Future<Account> updatePassword({required String password});
|
Future<Account> updatePassword({required String password});
|
||||||
|
|
||||||
|
/// Delete the current account.
|
||||||
Future<void> delete();
|
Future<void> delete();
|
||||||
|
|
||||||
// Email related stuff ======================================================
|
// Email related stuff ======================================================
|
||||||
|
|
||||||
|
/// Send an email verification.
|
||||||
Future<void> sendEmailVerification();
|
Future<void> sendEmailVerification();
|
||||||
|
|
||||||
|
/// Send a password reset email.
|
||||||
Future<void> sendPasswordResetEmail({required String email});
|
Future<void> sendPasswordResetEmail({required String email});
|
||||||
|
|
||||||
|
/// Confirm password reset.
|
||||||
Future<void> confirmPasswordReset({
|
Future<void> confirmPasswordReset({
|
||||||
required String code,
|
required String code,
|
||||||
required String newPassword,
|
required String newPassword,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Verify password reset code.
|
||||||
Future<bool> verifyPasswordResetCode({required String 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_authentication_bloc/src/domain/entities/auth_session.dart';
|
||||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||||
|
|
||||||
|
/// {@template auth_repo}
|
||||||
|
/// Authentication repository interface.
|
||||||
|
/// {@endtemplate}
|
||||||
abstract class AuthenticationRepository<Data> extends BaseRepository {
|
abstract class AuthenticationRepository<Data> extends BaseRepository {
|
||||||
/// {@template form_repo}
|
/// {@template form_repo}
|
||||||
/// Form repository used in different authentication cubits/blocs
|
/// Form repository used in different authentication cubits/blocs
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
FormRepository get formRepository;
|
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}
|
/// {@template add_session}
|
||||||
/// Add a new authentication event.
|
/// Add a new authentication event.
|
||||||
|
@ -27,27 +27,45 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
|||||||
|
|
||||||
part 'authentication_state.dart';
|
part 'authentication_state.dart';
|
||||||
|
|
||||||
|
/// {@template authentication_cubit}
|
||||||
/// Abstract authentication cubit class needs to be implemented in application.
|
/// Abstract authentication cubit class needs to be implemented in application.
|
||||||
///
|
///
|
||||||
/// This cubit is in charge of managing the global authentication state of
|
/// This cubit is in charge of managing the global authentication state of
|
||||||
/// the application.
|
/// the application.
|
||||||
///
|
///
|
||||||
/// Its here you can override every callbacks and add your custom logic.
|
/// Its here you can override every callbacks and add your custom logic.
|
||||||
|
/// {@endtemplate}
|
||||||
abstract class AuthenticationCubit<Data>
|
abstract class AuthenticationCubit<Data>
|
||||||
extends Cubit<AuthenticationState<Data>> {
|
extends Cubit<AuthenticationState<Data>> {
|
||||||
|
/// {@macro authentication_cubit}
|
||||||
AuthenticationCubit({
|
AuthenticationCubit({
|
||||||
required this.authenticationRepository,
|
required this.authenticationRepository,
|
||||||
}) : super(const AuthenticationState.unknown()) {
|
}) : super(const AuthenticationState.unknown()) {
|
||||||
_listenForAuthenticationChanges();
|
_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The authentication repository.
|
||||||
final AuthenticationRepository<Data> authenticationRepository;
|
final AuthenticationRepository<Data> authenticationRepository;
|
||||||
|
|
||||||
|
/// The latest session.
|
||||||
AuthenticationSession<Data>? _latestSession;
|
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() {
|
void _listenForAuthenticationChanges() {
|
||||||
authenticationRepository.sessionStream().asyncMap((session) async {
|
authenticationRepository.sessionStream().asyncMap((session) async {
|
||||||
final event = session.latestEvent;
|
final event = session.latestEvent;
|
||||||
|
|
||||||
|
/// If the session is signed in from cache.
|
||||||
if (event is SignedInFromCacheEvent) {
|
if (event is SignedInFromCacheEvent) {
|
||||||
|
/// Call the custom routine.
|
||||||
final customRoutineResult = await onSignInFromCache(session);
|
final customRoutineResult = await onSignInFromCache(session);
|
||||||
|
|
||||||
if (customRoutineResult.isOk) {
|
if (customRoutineResult.isOk) {
|
||||||
@ -64,12 +82,18 @@ abstract class AuthenticationCubit<Data>
|
|||||||
}
|
}
|
||||||
return session;
|
return session;
|
||||||
}).listen((session) async {
|
}).listen((session) async {
|
||||||
|
/// Save the latest session.
|
||||||
_latestSession = session;
|
_latestSession = session;
|
||||||
|
|
||||||
|
/// If there is an account: emit authenticated state.
|
||||||
if (session.account != null) {
|
if (session.account != null) {
|
||||||
emit(AuthenticationState<Data>.authenticated(session));
|
emit(AuthenticationState<Data>.authenticated(session));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If there is no account: emit unauthenticated state.
|
||||||
emit(AuthenticationState<Data>.unauthenticated());
|
emit(AuthenticationState<Data>.unauthenticated());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user