milestone/stable-1-reconcile-auth-3 #176
@ -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