diff --git a/lib/components/app_drawer.dart b/lib/components/app_drawer.dart index 1ef5958..1437741 100644 --- a/lib/components/app_drawer.dart +++ b/lib/components/app_drawer.dart @@ -3,6 +3,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import '../app_router.dart'; +import '../data/repositories/auth_facade.dart'; // statefull app drawer class AppDrawer extends StatefulWidget { @@ -13,8 +14,11 @@ class AppDrawer extends StatefulWidget { } class _AppDrawerState extends State { + final _authFacade = AuthFacade(); + void signOut(BuildContext context) async { - await Auth.signOut(); + await _authFacade.signOut(); + context.router.push(const LoginRoute()); } diff --git a/lib/data/models/user.dart b/lib/data/models/user.dart new file mode 100644 index 0000000..a0252f2 --- /dev/null +++ b/lib/data/models/user.dart @@ -0,0 +1,20 @@ +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'user.g.dart'; + +@JsonSerializable() +class User extends Equatable { + final String id; + final String? email; + final String? username; + + const User({required this.id, required this.email, required this.username}); + + @override + List get props => [id, email, username]; + + factory User.fromJson(Map json) => _$UserFromJson(json); + + Map toJson() => _$UserToJson(this); +} diff --git a/lib/data/models/user.g.dart b/lib/data/models/user.g.dart new file mode 100644 index 0000000..3b2b4ce --- /dev/null +++ b/lib/data/models/user.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +User _$UserFromJson(Map json) => User( + id: json['id'] as String, + email: json['email'] as String?, + username: json['username'] as String?, + ); + +Map _$UserToJson(User instance) => { + 'id': instance.id, + 'email': instance.email, + 'username': instance.username, + }; diff --git a/lib/data/repositories/auth_facade.dart b/lib/data/repositories/auth_facade.dart new file mode 100644 index 0000000..582c3f6 --- /dev/null +++ b/lib/data/repositories/auth_facade.dart @@ -0,0 +1,34 @@ +import 'package:auth/auth.dart'; +import 'package:injectable/injectable.dart'; + +import '../models/user.dart'; + +@Injectable() +class AuthFacade { + Future signIn({ + required String email, + required String password, + }) { + return Auth.signInWithEmailAndPassword(email: email, password: password); + } + + Future register( + {required String username, + required String email, + required String password}) { + return Auth.createUserWithEmailAndPassword( + email: email, password: password); + } + + User? getUser() { + final user = Auth.currentUser; + + return user == null + ? null + : User(id: user.uid, email: user.email, username: user.displayName); + } + + Future signOut() { + return Auth.signOut(); + } +} diff --git a/lib/injection.config.dart b/lib/injection.config.dart index 8fb4d27..0b98d5b 100644 --- a/lib/injection.config.dart +++ b/lib/injection.config.dart @@ -5,21 +5,36 @@ // ************************************************************************** // ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:flutter/material.dart' as _i6; +import 'package:flutter_bootstrap/data/repositories/auth_facade.dart' as _i3; +import 'package:flutter_bootstrap/pages/login.dart' as _i5; +import 'package:flutter_bootstrap/services/firebase_auth.dart' as _i4; import 'package:get_it/get_it.dart' as _i1; import 'package:injectable/injectable.dart' as _i2; +import 'injection.dart' as _i7; + // ignore_for_file: unnecessary_lambdas // ignore_for_file: lines_longer_than_80_chars // initializes the registration of main-scope dependencies inside of GetIt -_i1.GetIt $initGetIt( +Future<_i1.GetIt> $initGetIt( _i1.GetIt getIt, { String? environment, _i2.EnvironmentFilter? environmentFilter, -}) { +}) async { final gh = _i2.GetItHelper( getIt, environment, environmentFilter, ); + final appModule = _$AppModule(); + gh.factory<_i3.AuthFacade>(() => _i3.AuthFacade()); + await gh.factoryAsync<_i4.FirebaseAuthService>( + () => appModule.authService, + preResolve: true, + ); + gh.factory<_i5.LoginPage>(() => _i5.LoginPage(key: gh<_i6.Key>())); return getIt; } + +class _$AppModule extends _i7.AppModule {} diff --git a/lib/injection.dart b/lib/injection.dart index 2f35399..a822cb8 100644 --- a/lib/injection.dart +++ b/lib/injection.dart @@ -2,6 +2,7 @@ import 'package:get_it/get_it.dart'; import 'package:injectable/injectable.dart'; import 'injection.config.dart'; +import 'services/firebase_auth.dart'; final getIt = GetIt.instance; @@ -10,4 +11,10 @@ final getIt = GetIt.instance; preferRelativeImports: true, asExtension: false, ) -void configureDependencies() => $initGetIt(getIt); +Future configureDependencies() async => await $initGetIt(getIt); + +@module +abstract class AppModule { + @preResolve + Future get authService => FirebaseAuthService.init(); +} diff --git a/lib/main.dart b/lib/main.dart index 04ac7d4..8f89087 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:auth/auth.dart'; +import 'package:flutter_bootstrap/data/repositories/auth_facade.dart'; import 'injection.dart'; import 'app_router.dart'; @@ -8,11 +8,11 @@ import 'app_router.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); - configureDependencies(); - await Auth.initialize(); + await configureDependencies(); // TODO: use a guard to redirect to home if logged in - await Auth.signOut(); + final authFacade = AuthFacade(); + await authFacade.signOut(); runApp(MyApp()); } diff --git a/lib/pages/login.dart b/lib/pages/login.dart index 7e8559b..dddabca 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -1,11 +1,13 @@ // import 'dart:convert'; -import 'package:auth/auth.dart'; import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bootstrap/data/repositories/auth_facade.dart'; +import 'package:injectable/injectable.dart'; import '../app_router.dart'; +@Injectable() class LoginPage extends StatefulWidget { const LoginPage({Key? key}) : super(key: key); @@ -15,16 +17,18 @@ class LoginPage extends StatefulWidget { // login form in dart class _LoginState extends State { + final _authFacade = AuthFacade(); + final _formKey = GlobalKey(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); // async function to login Future login(BuildContext context) async { - await Auth.signInWithEmailAndPassword( + await _authFacade.signIn( email: _emailController.text, password: _passwordController.text); - if (Auth.currentUser != null) { + if (_authFacade.getUser() != null) { context.router.push(const HomeRoute()); } else { ScaffoldMessenger.of(context).showSnackBar( diff --git a/lib/services/firebase_auth.dart b/lib/services/firebase_auth.dart new file mode 100644 index 0000000..193dd12 --- /dev/null +++ b/lib/services/firebase_auth.dart @@ -0,0 +1,9 @@ +import 'package:auth/auth.dart'; + +class FirebaseAuthService { + static Future init() async { + await Auth.initialize(); + + return FirebaseAuthService(); + } +} diff --git a/pubspec.lock b/pubspec.lock index 966a43f..e0519d8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -208,6 +208,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.4" + equatable: + dependency: "direct main" + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" fake_async: dependency: transitive description: @@ -408,7 +416,7 @@ packages: source: hosted version: "0.6.5" json_annotation: - dependency: transitive + dependency: "direct main" description: name: json_annotation sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 diff --git a/pubspec.yaml b/pubspec.yaml index 0e3310f..94ca54d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,8 +32,10 @@ dependencies: sdk: flutter auto_route: ^5.0.4 + equatable: ^2.0.5 freezed_annotation: ^2.2.0 get_it: ^7.2.0 + json_annotation: ^4.8.0 injectable: ^2.1.0 logger: ^1.2.2