From 4d872edc4e83184189de23c0c3ca6c6bbee0b047 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Wed, 8 Mar 2023 12:57:56 +0100 Subject: [PATCH] docs(authentication): update example with multiple data sources --- .../example/README.md | 18 +---- .../example/ios/Podfile.lock | 16 ++-- .../ios/Runner.xcodeproj/project.pbxproj | 4 + .../ios/Runner/GoogleService-Info.plist | 38 ++++++++++ .../example/lib/bootstrap.dart | 9 --- .../lib/core/dependency_injection/get_it.dart | 73 +++++++++++++++++-- .../example/lib/core/enums/dev_mode.dart | 44 +++++++++++ .../example/lib/core/flavors/flavor.dart | 72 ++++++++++++++++++ .../example/lib/firebase_options.dart | 6 +- .../example/lib/main.dart | 8 +- ...in_firebase.dart => main_development.dart} | 8 +- .../lib/presentation/features/app/app.dart | 3 + .../presentation/features/sub/sub_page.dart | 3 +- 13 files changed, 261 insertions(+), 41 deletions(-) create mode 100644 packages/wyatt_authentication_bloc/example/ios/Runner/GoogleService-Info.plist create mode 100644 packages/wyatt_authentication_bloc/example/lib/core/enums/dev_mode.dart create mode 100644 packages/wyatt_authentication_bloc/example/lib/core/flavors/flavor.dart rename packages/wyatt_authentication_bloc/example/lib/{main_firebase.dart => main_development.dart} (82%) diff --git a/packages/wyatt_authentication_bloc/example/README.md b/packages/wyatt_authentication_bloc/example/README.md index 139e82ee..df389404 100644 --- a/packages/wyatt_authentication_bloc/example/README.md +++ b/packages/wyatt_authentication_bloc/example/README.md @@ -1,16 +1,6 @@ # example_router -A new Flutter project. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +```sh +firebase emulators:start --only auth +flutter run --target lib/main_development.dart --dart-define="dev_mode=emulator" +``` diff --git a/packages/wyatt_authentication_bloc/example/ios/Podfile.lock b/packages/wyatt_authentication_bloc/example/ios/Podfile.lock index bc6894a5..4e5cbe34 100644 --- a/packages/wyatt_authentication_bloc/example/ios/Podfile.lock +++ b/packages/wyatt_authentication_bloc/example/ios/Podfile.lock @@ -10,11 +10,11 @@ PODS: - FirebaseAuth (~> 10.3.0) - Firebase/CoreOnly (10.3.0): - FirebaseCore (= 10.3.0) - - firebase_auth (4.2.0): + - firebase_auth (4.2.9): - Firebase/Auth (= 10.3.0) - firebase_core - Flutter - - firebase_core (2.4.0): + - firebase_core (2.7.0): - Firebase/CoreOnly (= 10.3.0) - Flutter - FirebaseAuth (10.3.0): @@ -29,6 +29,8 @@ PODS: - FirebaseCoreInternal (10.3.0): - "GoogleUtilities/NSData+zlib (~> 7.8)" - Flutter (1.0.0) + - flutter_secure_storage (6.0.0): + - Flutter - google_sign_in_ios (0.0.1): - Flutter - GoogleSignIn (~> 6.2) @@ -61,6 +63,7 @@ DEPENDENCIES: - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - Flutter (from `Flutter`) + - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`) SPEC REPOS: @@ -83,19 +86,22 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/firebase_core/ios" Flutter: :path: Flutter + flutter_secure_storage: + :path: ".symlinks/plugins/flutter_secure_storage/ios" google_sign_in_ios: :path: ".symlinks/plugins/google_sign_in_ios/ios" SPEC CHECKSUMS: AppAuth: 8fca6b5563a5baef2c04bee27538025e4ceb2add Firebase: f92fc551ead69c94168d36c2b26188263860acd9 - firebase_auth: 579a0dc15451491cc83fccaa5102296635f24938 - firebase_core: 6f2f753e316765799d88568232ed59e300ff53db + firebase_auth: 4e8c693e848ed13b263de2d702d55fa82ed04a79 + firebase_core: 128d8c43c3a453a4a67463314fc3761bedff860b FirebaseAuth: 0e415d29d846c1dce2fb641e46f35e9888d9bec6 FirebaseCore: 988754646ab3bd4bdcb740f1bfe26b9f6c0d5f2a FirebaseCoreInternal: 29b76f784d607df8b2a1259d73c3f04f1210137b Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - google_sign_in_ios: 4f85eb9f937450765c8573bb85fd8cd6a5af675c + flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be + google_sign_in_ios: 1256ff9d941db546373826966720b0c24804bcdd GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a GoogleUtilities: bad72cb363809015b1f7f19beb1f1cd23c589f95 GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd diff --git a/packages/wyatt_authentication_bloc/example/ios/Runner.xcodeproj/project.pbxproj b/packages/wyatt_authentication_bloc/example/ios/Runner.xcodeproj/project.pbxproj index 85497888..eda3ed8b 100644 --- a/packages/wyatt_authentication_bloc/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/wyatt_authentication_bloc/example/ios/Runner.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 44F5B6790A35D9BA26574F6B /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F6E17622FCECE9BFC2543397 /* GoogleService-Info.plist */; }; 69F3BBCD5DEB05A456F6B74F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0A061B2E527F311149C3581 /* Pods_Runner.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -46,6 +47,7 @@ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B0A061B2E527F311149C3581 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F0D7945BAE0BEA457137ED73 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + F6E17622FCECE9BFC2543397 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; F9340E3A859C31E59380BD0F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -91,6 +93,7 @@ 97C146EF1CF9000F007C117D /* Products */, 66B357379C2757D2844F12BB /* Pods */, BC1E25CE0DADDF7B7201CCF8 /* Frameworks */, + F6E17622FCECE9BFC2543397 /* GoogleService-Info.plist */, ); sourceTree = ""; }; @@ -192,6 +195,7 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + 44F5B6790A35D9BA26574F6B /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/wyatt_authentication_bloc/example/ios/Runner/GoogleService-Info.plist b/packages/wyatt_authentication_bloc/example/ios/Runner/GoogleService-Info.plist new file mode 100644 index 00000000..ac60a458 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,38 @@ + + + + + CLIENT_ID + 136771801992-p629tpo9bk3hcm2955s5ahivdla57ln9.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.136771801992-p629tpo9bk3hcm2955s5ahivdla57ln9 + ANDROID_CLIENT_ID + 136771801992-n2pq8oqutvrqj58e05hbavvc7n1jdfjb.apps.googleusercontent.com + API_KEY + AIzaSyCDbbhjbFrQwLXuIANdJzjkDk8uOETnn7w + GCM_SENDER_ID + 136771801992 + PLIST_VERSION + 1 + BUNDLE_ID + com.example.exampleRouter + PROJECT_ID + tchat-beta + STORAGE_BUCKET + tchat-beta.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:136771801992:ios:bcdca68d2b7d227097203d + DATABASE_URL + https://tchat-beta.firebaseio.com + + \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/example/lib/bootstrap.dart b/packages/wyatt_authentication_bloc/example/lib/bootstrap.dart index 05ee6358..948e01fd 100644 --- a/packages/wyatt_authentication_bloc/example/lib/bootstrap.dart +++ b/packages/wyatt_authentication_bloc/example/lib/bootstrap.dart @@ -18,11 +18,8 @@ import 'dart:async'; import 'package:example_router/core/dependency_injection/get_it.dart'; import 'package:example_router/core/utils/app_bloc_observer.dart'; -import 'package:example_router/firebase_options.dart'; -import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; class MockSettings { static MockSettings? _instance; @@ -70,12 +67,6 @@ Future bootstrap(FutureOr Function() builder) async { debugPrint(details.toString()); }; - if (MockSettings.isDisable()) { - await Firebase.initializeApp( - options: DefaultFirebaseOptions.currentPlatform, - ); - await FirebaseAuth.instance.useAuthEmulator('localhost', 9099); - } await GetItInitializer.init(); runApp(await builder()); diff --git a/packages/wyatt_authentication_bloc/example/lib/core/dependency_injection/get_it.dart b/packages/wyatt_authentication_bloc/example/lib/core/dependency_injection/get_it.dart index 1490523f..a4833f56 100644 --- a/packages/wyatt_authentication_bloc/example/lib/core/dependency_injection/get_it.dart +++ b/packages/wyatt_authentication_bloc/example/lib/core/dependency_injection/get_it.dart @@ -14,20 +14,81 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +import 'dart:async'; + +import 'package:example_router/core/enums/dev_mode.dart'; +import 'package:example_router/core/flavors/flavor.dart'; import 'package:example_router/firebase_options.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:get_it/get_it.dart'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; final getIt = GetIt.I; +/// Service and Data Source locator abstract class GetItInitializer { - static Future init() async { - getIt.registerLazySingleton>( - () => AuthenticationFirebaseDataSourceImpl( - firebaseAuth: FirebaseAuth.instance, - googleSignIn: - GoogleSignIn(clientId: DefaultFirebaseOptions.ios.iosClientId)), + static FutureOr _initCommon() async { + // Initialize common sources/services + getIt.registerLazySingleton>( + () => AuthenticationSessionDataSourceImpl(), ); + } + + static FutureOr _initEmulator() async { + // Initialize emulator sources/services + final firebaseAuth = FirebaseAuth.instance; + await firebaseAuth.useAuthEmulator('localhost', 9099); + getIt + ..registerLazySingleton>( + () => AuthenticationFirebaseDataSourceImpl( + firebaseAuth: firebaseAuth, + googleSignIn: + GoogleSignIn(clientId: DefaultFirebaseOptions.ios.iosClientId)), + ) + ..registerLazySingleton>( + () => AuthenticationFirebaseCacheDataSourceImpl( + firebaseAuth: firebaseAuth, + ), + ); + } + + static FutureOr _initFirebase() async { + // Initialize firebase sources/services. + getIt + ..registerLazySingleton>( + () => AuthenticationFirebaseDataSourceImpl( + firebaseAuth: FirebaseAuth.instance, + googleSignIn: + GoogleSignIn(clientId: DefaultFirebaseOptions.ios.iosClientId)), + ) + ..registerLazySingleton>( + () => AuthenticationFirebaseCacheDataSourceImpl( + firebaseAuth: FirebaseAuth.instance, + ), + ); + } + + static FutureOr _initRest() async { + // Initialize rest api sources/services + } + + static FutureOr init() async { + await _initCommon(); + final flavor = Flavor.get(); + + if (flavor.devMode == DevMode.rest) { + await _initRest(); + } else if (flavor.devMode == DevMode.emulator) { + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + await _initEmulator(); + } else { + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + await _initFirebase(); + } await getIt.allReady(); } diff --git a/packages/wyatt_authentication_bloc/example/lib/core/enums/dev_mode.dart b/packages/wyatt_authentication_bloc/example/lib/core/enums/dev_mode.dart new file mode 100644 index 00000000..5c99b7f8 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example/lib/core/enums/dev_mode.dart @@ -0,0 +1,44 @@ +// 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 . + +enum DevMode { + /// Mocked values + mock, + + /// Real values from REST API + rest, + + /// Emulated values with Firebase Emulator + emulator, + + /// Real values from Firebase + real; + + @override + String toString() => name; + + /// Tries to parse String and returns mode. Fallback is returned if there + /// is an error during parsing. + static DevMode fromString(String? mode, {DevMode fallback = DevMode.mock}) { + for (final m in values) { + if (m.name == mode) { + return m; + } + } + + return fallback; + } +} diff --git a/packages/wyatt_authentication_bloc/example/lib/core/flavors/flavor.dart b/packages/wyatt_authentication_bloc/example/lib/core/flavors/flavor.dart new file mode 100644 index 00000000..9fef201a --- /dev/null +++ b/packages/wyatt_authentication_bloc/example/lib/core/flavors/flavor.dart @@ -0,0 +1,72 @@ +// 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 . + +import 'package:example_router/core/enums/dev_mode.dart'; +import 'package:flutter/material.dart'; + +abstract class Flavor { + Flavor._({ + this.banner, + this.bannerColor = Colors.red, + this.devMode, + }) { + _instance = this; + } + + static Flavor? _instance; + + final String? banner; + final Color bannerColor; + final DevMode? devMode; + + /// Returns [Flavor] instance. + static Flavor get() { + if (_instance == null) { + throw Exception('Flavor not initialized!'); + } + + return _instance!; + } + + @override + String toString() => runtimeType.toString().replaceAll('Flavor', ''); +} + +class DevelopmentFlavor extends Flavor { + factory DevelopmentFlavor() { + const modeString = String.fromEnvironment('dev_mode', defaultValue: 'mock'); + final mode = DevMode.fromString(modeString); + + return DevelopmentFlavor._(devMode: mode); + } + DevelopmentFlavor._({ + required super.devMode, + }) : super._( + banner: 'Dev', + ); +} + +class StagingFlavor extends Flavor { + StagingFlavor() + : super._( + banner: 'Staging', + bannerColor: Colors.green, + ); +} + +class ProductionFlavor extends Flavor { + ProductionFlavor() : super._(); +} diff --git a/packages/wyatt_authentication_bloc/example/lib/firebase_options.dart b/packages/wyatt_authentication_bloc/example/lib/firebase_options.dart index dcf7c17e..0725ddb4 100644 --- a/packages/wyatt_authentication_bloc/example/lib/firebase_options.dart +++ b/packages/wyatt_authentication_bloc/example/lib/firebase_options.dart @@ -65,8 +65,10 @@ class DefaultFirebaseOptions { projectId: 'tchat-beta', databaseURL: 'https://tchat-beta.firebaseio.com', storageBucket: 'tchat-beta.appspot.com', - androidClientId: '136771801992-n2pq8oqutvrqj58e05hbavvc7n1jdfjb.apps.googleusercontent.com', - iosClientId: '136771801992-p629tpo9bk3hcm2955s5ahivdla57ln9.apps.googleusercontent.com', + androidClientId: + '136771801992-n2pq8oqutvrqj58e05hbavvc7n1jdfjb.apps.googleusercontent.com', + iosClientId: + '136771801992-p629tpo9bk3hcm2955s5ahivdla57ln9.apps.googleusercontent.com', iosBundleId: 'com.example.exampleRouter', ); } diff --git a/packages/wyatt_authentication_bloc/example/lib/main.dart b/packages/wyatt_authentication_bloc/example/lib/main.dart index a7967932..a8d69968 100644 --- a/packages/wyatt_authentication_bloc/example/lib/main.dart +++ b/packages/wyatt_authentication_bloc/example/lib/main.dart @@ -15,9 +15,13 @@ // along with this program. If not, see . import 'package:example_router/bootstrap.dart'; +import 'package:example_router/core/flavors/flavor.dart'; import 'package:example_router/presentation/features/app/app.dart'; -void main() { - MockSettings.enable(); +void main(List args) { + // Define environment + ProductionFlavor(); + + // Initialize environment and variables bootstrap(App.new); } diff --git a/packages/wyatt_authentication_bloc/example/lib/main_firebase.dart b/packages/wyatt_authentication_bloc/example/lib/main_development.dart similarity index 82% rename from packages/wyatt_authentication_bloc/example/lib/main_firebase.dart rename to packages/wyatt_authentication_bloc/example/lib/main_development.dart index 62ee35ec..9025e30f 100644 --- a/packages/wyatt_authentication_bloc/example/lib/main_firebase.dart +++ b/packages/wyatt_authentication_bloc/example/lib/main_development.dart @@ -15,9 +15,13 @@ // along with this program. If not, see . import 'package:example_router/bootstrap.dart'; +import 'package:example_router/core/flavors/flavor.dart'; import 'package:example_router/presentation/features/app/app.dart'; -void main() { - MockSettings.disable(); +void main(List args) { + // Define environment + DevelopmentFlavor(); + + // Initialize environment and variables bootstrap(App.new); } diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/app/app.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/app/app.dart index 5285f63d..51b038d9 100644 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/app/app.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/app/app.dart @@ -34,6 +34,9 @@ class App extends StatelessWidget { AuthenticationRepositoryImpl( authenticationRemoteDataSource: getIt>(), + authenticationSessionDataSource: + getIt>(), + authenticationCacheDataSource: getIt>(), customPasswordValidator: const CustomPassword.pure(), extraSignUpInputs: [ FormInput( diff --git a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sub/sub_page.dart b/packages/wyatt_authentication_bloc/example/lib/presentation/features/sub/sub_page.dart index 9c0f4ece..f56df50b 100644 --- a/packages/wyatt_authentication_bloc/example/lib/presentation/features/sub/sub_page.dart +++ b/packages/wyatt_authentication_bloc/example/lib/presentation/features/sub/sub_page.dart @@ -45,7 +45,8 @@ class SubPage extends StatelessWidget { children: [ const Text('Another page'), ElevatedButton( - onPressed: () => context.read>().delete(), + onPressed: () => + context.read>().delete(), child: const Text('Delete account'), ), ],