From 874507d14b14eea79f52184e70c7201c61dabde5 Mon Sep 17 00:00:00 2001 From: Jorge Coca Date: Sat, 30 Apr 2022 11:51:26 -0500 Subject: [PATCH] feat(authentication_repository): support anonymous authentication (#269) --- .../workflows/authentication_repository.yaml | 22 ++++++++++ packages/authentication_repository/.gitignore | 39 ++++++++++++++++++ packages/authentication_repository/README.md | 11 +++++ .../analysis_options.yaml | 1 + .../lib/authentication_repository.dart | 3 ++ .../lib/src/authentication_repository.dart | 36 +++++++++++++++++ .../authentication_repository/pubspec.yaml | 18 +++++++++ .../src/authentication_repository_test.dart | 40 +++++++++++++++++++ pubspec.lock | 30 +++++++++++++- pubspec.yaml | 3 ++ 10 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/authentication_repository.yaml create mode 100644 packages/authentication_repository/.gitignore create mode 100644 packages/authentication_repository/README.md create mode 100644 packages/authentication_repository/analysis_options.yaml create mode 100644 packages/authentication_repository/lib/authentication_repository.dart create mode 100644 packages/authentication_repository/lib/src/authentication_repository.dart create mode 100644 packages/authentication_repository/pubspec.yaml create mode 100644 packages/authentication_repository/test/src/authentication_repository_test.dart diff --git a/.github/workflows/authentication_repository.yaml b/.github/workflows/authentication_repository.yaml new file mode 100644 index 00000000..74c81d10 --- /dev/null +++ b/.github/workflows/authentication_repository.yaml @@ -0,0 +1,22 @@ +name: authentication_repository + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + paths: + - "packages/authentication_repository/**" + - ".github/workflows/authentication_repository.yaml" + + pull_request: + paths: + - "packages/authentication_repository/**" + - ".github/workflows/authentication_repository.yaml" + +jobs: + build: + uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1 + with: + working_directory: packages/authentication_repository diff --git a/packages/authentication_repository/.gitignore b/packages/authentication_repository/.gitignore new file mode 100644 index 00000000..d6130351 --- /dev/null +++ b/packages/authentication_repository/.gitignore @@ -0,0 +1,39 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# VSCode related +.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json diff --git a/packages/authentication_repository/README.md b/packages/authentication_repository/README.md new file mode 100644 index 00000000..8f56b868 --- /dev/null +++ b/packages/authentication_repository/README.md @@ -0,0 +1,11 @@ +# authentication_repository + +[![style: very good analysis][very_good_analysis_badge]][very_good_analysis_link] +[![License: MIT][license_badge]][license_link] + +Repository to manage user authentication. + +[license_badge]: https://img.shields.io/badge/license-MIT-blue.svg +[license_link]: https://opensource.org/licenses/MIT +[very_good_analysis_badge]: https://img.shields.io/badge/style-very_good_analysis-B22C89.svg +[very_good_analysis_link]: https://pub.dev/packages/very_good_analysis \ No newline at end of file diff --git a/packages/authentication_repository/analysis_options.yaml b/packages/authentication_repository/analysis_options.yaml new file mode 100644 index 00000000..3742fc3d --- /dev/null +++ b/packages/authentication_repository/analysis_options.yaml @@ -0,0 +1 @@ +include: package:very_good_analysis/analysis_options.2.4.0.yaml \ No newline at end of file diff --git a/packages/authentication_repository/lib/authentication_repository.dart b/packages/authentication_repository/lib/authentication_repository.dart new file mode 100644 index 00000000..77b1b6b9 --- /dev/null +++ b/packages/authentication_repository/lib/authentication_repository.dart @@ -0,0 +1,3 @@ +library authentication_repository; + +export 'src/authentication_repository.dart'; diff --git a/packages/authentication_repository/lib/src/authentication_repository.dart b/packages/authentication_repository/lib/src/authentication_repository.dart new file mode 100644 index 00000000..9f252518 --- /dev/null +++ b/packages/authentication_repository/lib/src/authentication_repository.dart @@ -0,0 +1,36 @@ +import 'package:firebase_auth/firebase_auth.dart'; + +/// {@template authentication_exception} +/// Exception for authentication repository failures. +/// {@endtemplate} +class AuthenticationException implements Exception { + /// {@macro authentication_exception} + const AuthenticationException(this.error, this.stackTrace); + + /// The error that was caught. + final Object error; + + /// The Stacktrace associated with the [error]. + final StackTrace stackTrace; +} + +/// {@template authentication_repository} +/// Repository to manage user authentication. +/// {@endtemplate} +class AuthenticationRepository { + /// {@macro authentication_repository} + AuthenticationRepository(this._firebaseAuth); + + final FirebaseAuth _firebaseAuth; + + /// Sign in the existing user anonymously using [FirebaseAuth]. If the + /// authentication process can't be completed, it will throw an + /// [AuthenticationException]. + Future authenticateAnonymously() async { + try { + await _firebaseAuth.signInAnonymously(); + } on Exception catch (error, stackTrace) { + throw AuthenticationException(error, stackTrace); + } + } +} diff --git a/packages/authentication_repository/pubspec.yaml b/packages/authentication_repository/pubspec.yaml new file mode 100644 index 00000000..bac20507 --- /dev/null +++ b/packages/authentication_repository/pubspec.yaml @@ -0,0 +1,18 @@ +name: authentication_repository +description: Repository to manage user authentication. +version: 1.0.0+1 +publish_to: none + +environment: + sdk: ">=2.16.0 <3.0.0" + +dependencies: + firebase_auth: ^3.3.16 + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + mocktail: ^0.2.0 + very_good_analysis: ^2.4.0 \ No newline at end of file diff --git a/packages/authentication_repository/test/src/authentication_repository_test.dart b/packages/authentication_repository/test/src/authentication_repository_test.dart new file mode 100644 index 00000000..a179bb68 --- /dev/null +++ b/packages/authentication_repository/test/src/authentication_repository_test.dart @@ -0,0 +1,40 @@ +import 'package:authentication_repository/authentication_repository.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +class MockFirebaseAuth extends Mock implements FirebaseAuth {} + +class MockUserCredential extends Mock implements UserCredential {} + +void main() { + late FirebaseAuth firebaseAuth; + late UserCredential userCredential; + late AuthenticationRepository authenticationRepository; + + group('AuthenticationRepository', () { + setUp(() { + firebaseAuth = MockFirebaseAuth(); + userCredential = MockUserCredential(); + authenticationRepository = AuthenticationRepository(firebaseAuth); + }); + + group('authenticateAnonymously', () { + test('completes if no exception is thrown', () async { + when(() => firebaseAuth.signInAnonymously()) + .thenAnswer((_) async => userCredential); + await authenticationRepository.authenticateAnonymously(); + verify(() => firebaseAuth.signInAnonymously()).called(1); + }); + + test('throws AuthenticationException when firebase auth fails', () async { + when(() => firebaseAuth.signInAnonymously()) + .thenThrow(Exception('oops')); + expect( + () => authenticationRepository.authenticateAnonymously(), + throwsA(isA()), + ); + }); + }); + }); +} diff --git a/pubspec.lock b/pubspec.lock index ab39378a..3b6d5d63 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -36,6 +36,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.20.1" + authentication_repository: + dependency: "direct main" + description: + path: "packages/authentication_repository" + relative: true + source: path + version: "1.0.0+1" bloc: dependency: "direct main" description: @@ -169,6 +176,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.1.2" + firebase_auth: + dependency: "direct main" + description: + name: firebase_auth + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.16" + firebase_auth_platform_interface: + dependency: transitive + description: + name: firebase_auth_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "6.2.4" + firebase_auth_web: + dependency: transitive + description: + name: firebase_auth_web + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.13" firebase_core: dependency: transitive description: @@ -189,7 +217,7 @@ packages: name: firebase_core_web url: "https://pub.dartlang.org" source: hosted - version: "1.6.1" + version: "1.6.2" flame: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 51c85cd5..c6866b2e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,9 +7,12 @@ environment: sdk: ">=2.16.0 <3.0.0" dependencies: + authentication_repository: + path: packages/authentication_repository bloc: ^8.0.2 cloud_firestore: ^3.1.10 equatable: ^2.0.3 + firebase_auth: ^3.3.16 flame: ^1.1.1 flame_bloc: ^1.2.0 flame_forge2d: