adding packages
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import './bloc.dart';
|
||||
import '../../../fb_auth.dart';
|
||||
import '../../classes/auth_user.dart';
|
||||
|
||||
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
AuthBloc({
|
||||
@required this.app,
|
||||
this.saveUser,
|
||||
this.deleteUser,
|
||||
}) : _auth = FBAuth(app);
|
||||
|
||||
final FbApp app;
|
||||
|
||||
final FBAuth _auth;
|
||||
|
||||
@override
|
||||
AuthState get initialState => InitialAuthState();
|
||||
|
||||
@override
|
||||
Stream<AuthState> mapEventToState(
|
||||
AuthEvent event,
|
||||
) async* {
|
||||
if (event is CheckUser) {
|
||||
yield* _mapCheckToState(event);
|
||||
}
|
||||
if (event is LoginEvent) {
|
||||
yield* _mapLoginToState(event);
|
||||
}
|
||||
if (event is LogoutEvent) {
|
||||
yield* _mapLogoutToState(event);
|
||||
}
|
||||
if (event is CreateAccount) {
|
||||
yield* _mapCreateToState(event);
|
||||
}
|
||||
if (event is UpdateUser) {
|
||||
yield* _mapUpdateToState(event);
|
||||
}
|
||||
if (event is EditInfo) {
|
||||
yield* _mapEditInfoToState(event);
|
||||
}
|
||||
if (event is ForgotPassword) {
|
||||
yield* _mapForgotPasswordToState(event);
|
||||
}
|
||||
if (event is SendEmailVerification) {
|
||||
yield* _mapVerifyToState(event);
|
||||
}
|
||||
if (event is LoginGuest) {
|
||||
yield* _mapGuestToState(event);
|
||||
}
|
||||
if (event is LoginGoogle) {
|
||||
yield* _mapGoogleToState(event);
|
||||
}
|
||||
if (event is ChangeUser) {
|
||||
yield LoggedInState(event.user);
|
||||
}
|
||||
}
|
||||
|
||||
/// Called every time the user info changes. You can use this method for updating a database.
|
||||
final Function(AuthUser) saveUser;
|
||||
|
||||
/// Called when the user logs out. You can use this method for updating a database.
|
||||
final Function() deleteUser;
|
||||
|
||||
Stream<AuthState> _mapGoogleToState(LoginGoogle event) async* {
|
||||
yield AuthLoadingState();
|
||||
final _user = await _auth.loginGoogle(
|
||||
idToken: event.idToken, accessToken: event.accessToken);
|
||||
if (_user != null) {
|
||||
if (saveUser != null) saveUser(_user);
|
||||
yield LoggedInState(_user);
|
||||
} else {
|
||||
yield LoggedOutState();
|
||||
}
|
||||
}
|
||||
|
||||
Stream<AuthState> _mapGuestToState(LoginGuest event) async* {
|
||||
yield AuthLoadingState();
|
||||
final _user = await _auth.startAsGuest();
|
||||
if (_user != null) {
|
||||
if (saveUser != null) saveUser(_user);
|
||||
yield LoggedInState(_user);
|
||||
} else {
|
||||
yield LoggedOutState();
|
||||
}
|
||||
}
|
||||
|
||||
Stream<AuthState> _mapCheckToState(CheckUser event) async* {
|
||||
yield AuthLoadingState();
|
||||
final _user = await _auth.currentUser();
|
||||
if (_user != null) {
|
||||
if (saveUser != null) saveUser(_user);
|
||||
yield LoggedInState(_user);
|
||||
} else {
|
||||
yield LoggedOutState();
|
||||
}
|
||||
}
|
||||
|
||||
Stream<AuthState> _mapCreateToState(CreateAccount event) async* {
|
||||
yield AuthLoadingState();
|
||||
try {
|
||||
AuthUser _user = await _auth.createAccount(event.username, event.password,
|
||||
displayName: event?.displayName, photoUrl: event?.photoUrl);
|
||||
if (_user != null) {
|
||||
if (saveUser != null) saveUser(_user);
|
||||
yield LoggedInState(_user);
|
||||
} else {
|
||||
yield AuthErrorState('Error creating user!');
|
||||
}
|
||||
} catch (e) {
|
||||
yield AuthErrorState('Email already exists!');
|
||||
}
|
||||
}
|
||||
|
||||
Stream<AuthState> _mapLoginToState(LoginEvent event) async* {
|
||||
yield AuthLoadingState();
|
||||
final _user = await _auth.login(event.username, event.password);
|
||||
if (_user != null) {
|
||||
if (saveUser != null) saveUser(_user);
|
||||
yield LoggedInState(_user);
|
||||
} else {
|
||||
yield AuthErrorState('Username or Password Incorrect!');
|
||||
}
|
||||
}
|
||||
|
||||
Stream<AuthState> _mapLogoutToState(LogoutEvent event) async* {
|
||||
yield AuthLoadingState();
|
||||
await _auth.logout();
|
||||
if (deleteUser != null) deleteUser();
|
||||
yield LoggedOutState();
|
||||
}
|
||||
|
||||
Stream<AuthState> _mapVerifyToState(SendEmailVerification event) async* {
|
||||
await _auth.sendEmailVerification();
|
||||
}
|
||||
|
||||
Stream<AuthState> _mapEditInfoToState(EditInfo event) async* {
|
||||
yield AuthLoadingState();
|
||||
await _auth.editInfo(
|
||||
displayName: event?.displayName, photoUrl: event?.photoUrl);
|
||||
final _user = await _auth.currentUser();
|
||||
if (saveUser != null) saveUser(_user);
|
||||
yield LoggedInState(_user);
|
||||
}
|
||||
|
||||
Stream<AuthState> _mapUpdateToState(UpdateUser event) async* {
|
||||
if (event?.user != null) {
|
||||
if (saveUser != null) saveUser(event.user);
|
||||
yield LoggedInState(event.user);
|
||||
} else {
|
||||
yield LoggedOutState();
|
||||
}
|
||||
}
|
||||
|
||||
Stream<AuthState> _mapForgotPasswordToState(ForgotPassword event) async* {
|
||||
await _auth.forgotPassword(event.email);
|
||||
}
|
||||
|
||||
static AuthUser currentUser(BuildContext context) {
|
||||
final auth = BlocProvider.of<AuthBloc>(context);
|
||||
final state = auth.state;
|
||||
if (state is LoggedInState) {
|
||||
return state.user;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import '../../classes/index.dart';
|
||||
|
||||
@immutable
|
||||
abstract class AuthEvent {}
|
||||
|
||||
class CheckUser extends AuthEvent {}
|
||||
|
||||
class LoginEvent extends AuthEvent {
|
||||
LoginEvent(this.username, this.password);
|
||||
|
||||
final String username, password;
|
||||
}
|
||||
|
||||
class LoginGuest extends AuthEvent {}
|
||||
|
||||
class CreateAccount extends AuthEvent {
|
||||
CreateAccount(this.username, this.password,
|
||||
{this.displayName, this.photoUrl});
|
||||
|
||||
final String username, password;
|
||||
final String displayName, photoUrl;
|
||||
}
|
||||
|
||||
class ChangeUser extends AuthEvent {
|
||||
ChangeUser(this.user);
|
||||
|
||||
final AuthUser user;
|
||||
}
|
||||
|
||||
class LogoutEvent extends AuthEvent {
|
||||
LogoutEvent(this.user);
|
||||
|
||||
final AuthUser user;
|
||||
}
|
||||
|
||||
class UpdateUser extends AuthEvent {
|
||||
UpdateUser(this.user);
|
||||
|
||||
final AuthUser user;
|
||||
}
|
||||
|
||||
class ForgotPassword extends AuthEvent {
|
||||
ForgotPassword(this.email);
|
||||
|
||||
final String email;
|
||||
}
|
||||
|
||||
class LoginGoogle extends AuthEvent {
|
||||
LoginGoogle({
|
||||
this.accessToken,
|
||||
this.idToken,
|
||||
});
|
||||
|
||||
final String idToken;
|
||||
final String accessToken;
|
||||
}
|
||||
|
||||
class SendEmailVerification extends AuthEvent {}
|
||||
|
||||
class EditInfo extends AuthEvent {
|
||||
EditInfo(this.user, {this.displayName, this.photoUrl});
|
||||
|
||||
final String displayName, photoUrl;
|
||||
final AuthUser user;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import '../../classes/index.dart';
|
||||
|
||||
@immutable
|
||||
abstract class AuthState {}
|
||||
|
||||
class InitialAuthState extends AuthState {}
|
||||
|
||||
class LoggedInState extends AuthState {
|
||||
LoggedInState(this.user);
|
||||
|
||||
final AuthUser user;
|
||||
}
|
||||
|
||||
class LoggedOutState extends AuthState {}
|
||||
|
||||
class AuthLoadingState extends AuthState {}
|
||||
|
||||
class AuthErrorState extends AuthState {
|
||||
AuthErrorState(this.message);
|
||||
|
||||
final String message;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export 'auth_bloc.dart';
|
||||
export 'auth_event.dart';
|
||||
export 'auth_state.dart';
|
||||
@@ -0,0 +1 @@
|
||||
export 'auth/bloc.dart';
|
||||
@@ -0,0 +1,21 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
|
||||
class SimpleBlocDelegate extends BlocDelegate {
|
||||
@override
|
||||
void onEvent(Bloc bloc, Object event) {
|
||||
super.onEvent(bloc, event);
|
||||
print(event);
|
||||
}
|
||||
|
||||
@override
|
||||
void onTransition(Bloc bloc, Transition transition) {
|
||||
super.onTransition(bloc, transition);
|
||||
print(transition);
|
||||
}
|
||||
|
||||
@override
|
||||
void onError(Bloc bloc, Object error, StackTrace stacktrace) {
|
||||
super.onError(bloc, error, stacktrace);
|
||||
print('$error, $stacktrace');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
class FbApp {
|
||||
FbApp({
|
||||
this.apiKey,
|
||||
this.authDomain,
|
||||
this.databaseURL,
|
||||
this.projectId,
|
||||
this.storageBucket,
|
||||
this.messagingSenderId,
|
||||
this.appId,
|
||||
this.measurementId,
|
||||
});
|
||||
|
||||
final String apiKey;
|
||||
final String authDomain;
|
||||
final String databaseURL;
|
||||
final String projectId;
|
||||
final String storageBucket;
|
||||
final String messagingSenderId;
|
||||
final String appId;
|
||||
final String measurementId;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class AuthUser {
|
||||
final String uid;
|
||||
final String displayName;
|
||||
final String email;
|
||||
final String photoUrl;
|
||||
|
||||
AuthUser({
|
||||
@required this.uid,
|
||||
@required this.displayName,
|
||||
@required this.email,
|
||||
@required this.isEmailVerified,
|
||||
@required this.isAnonymous,
|
||||
@required this.photoUrl,
|
||||
});
|
||||
final bool isEmailVerified;
|
||||
final bool isAnonymous;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '$displayName';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export 'app.dart';
|
||||
export 'auth_user.dart';
|
||||
@@ -0,0 +1,3 @@
|
||||
export 'unsupported.dart'
|
||||
if (dart.library.html) 'web.dart'
|
||||
if (dart.library.io) 'io.dart';
|
||||
@@ -0,0 +1,52 @@
|
||||
import '../../classes/index.dart';
|
||||
|
||||
abstract class FBAuthImpl {
|
||||
final FbApp app;
|
||||
|
||||
FBAuthImpl(this.app);
|
||||
|
||||
Future<AuthUser> login(String username, String password) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
Future<AuthUser> createAccount(String username, String password,
|
||||
{String displayName, String photoUrl}) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
Future logout() async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
Future<AuthUser> currentUser() async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
Future<AuthUser> startAsGuest() async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
Stream<AuthUser> onAuthChanged() {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
Future editInfo({String displayName, String photoUrl}) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
Future forgotPassword(String email) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
Future sendEmailVerification() async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
Future loginCustomToken(String token) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
Future loginGoogle({String idToken, String accessToken}) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import '../../classes/index.dart';
|
||||
import '../../utils/directory.dart';
|
||||
import '../mobile/sdk.dart';
|
||||
import '../rest_api/client.dart';
|
||||
import 'impl.dart';
|
||||
|
||||
class FBAuth implements FBAuthImpl {
|
||||
final FbApp app;
|
||||
final bool useRestClient;
|
||||
File _saveFile;
|
||||
|
||||
FBAuth(
|
||||
this.app, {
|
||||
this.useRestClient = false,
|
||||
}) {
|
||||
if (useClient) {
|
||||
_client = FbClient(
|
||||
app,
|
||||
onLoad: () async {
|
||||
await _loadFile();
|
||||
Map<String, dynamic> storage = Map<String, dynamic>();
|
||||
if (await _saveFile.exists()) {
|
||||
try {
|
||||
storage = json.decode(await _saveFile.readAsString())
|
||||
as Map<String, dynamic>;
|
||||
return storage;
|
||||
} catch (_) {
|
||||
await _saveFile.delete();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onSave: (data) async {
|
||||
try {
|
||||
if (data == null) {
|
||||
await _saveFile.delete();
|
||||
} else {
|
||||
await _saveFile.writeAsString(json.encode(data));
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
);
|
||||
}
|
||||
if (isMobile) {
|
||||
_sdk = FbSdk();
|
||||
}
|
||||
}
|
||||
|
||||
Future _loadFile() async {
|
||||
if (_saveFile == null) {
|
||||
final dir = await PathUtils.getDocumentDir();
|
||||
_saveFile = File('${dir.path}/fb_auth.json');
|
||||
}
|
||||
}
|
||||
|
||||
bool get useClient => isDesktop || useRestClient;
|
||||
static bool get isDesktop =>
|
||||
Platform.isWindows || Platform.isWindows || Platform.isMacOS;
|
||||
static bool get isMobile => Platform.isIOS || Platform.isAndroid;
|
||||
FbSdk _sdk;
|
||||
FbClient _client;
|
||||
@override
|
||||
Future<AuthUser> login(String username, String password) async {
|
||||
if (useClient) {
|
||||
await _loadFile();
|
||||
return _client.login(username, password);
|
||||
} else {
|
||||
return _sdk.login(username, password);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<AuthUser> onAuthChanged() {
|
||||
if (useClient) {
|
||||
return _client.onAuthChanged();
|
||||
} else {
|
||||
return _sdk.onAuthChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> startAsGuest() async {
|
||||
try {
|
||||
if (useClient) {
|
||||
await _loadFile();
|
||||
return _client.startAsGuest();
|
||||
} else {
|
||||
return _sdk.startAsGuest();
|
||||
}
|
||||
} catch (e) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future logout() async {
|
||||
if (useClient) {
|
||||
await _loadFile();
|
||||
await _client.logout();
|
||||
} else {
|
||||
await _sdk.logout();
|
||||
}
|
||||
try {
|
||||
await _saveFile.delete();
|
||||
} catch (e) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> currentUser() async {
|
||||
if (useClient) {
|
||||
await _loadFile();
|
||||
return _client.currentUser();
|
||||
} else {
|
||||
return _sdk.currentUser();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future editInfo({String displayName, String photoUrl}) async {
|
||||
if (useClient) {
|
||||
await _loadFile();
|
||||
return _client.editInfo(
|
||||
displayName: displayName,
|
||||
photoUrl: photoUrl,
|
||||
);
|
||||
} else {
|
||||
return _sdk.editInfo(
|
||||
displayName: displayName,
|
||||
photoUrl: photoUrl,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future forgotPassword(String email) async {
|
||||
if (useClient) {
|
||||
await _loadFile();
|
||||
return _client.forgotPassword(email);
|
||||
} else {
|
||||
return _sdk.forgotPassword(email);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future sendEmailVerification() async {
|
||||
if (useClient) {
|
||||
await _loadFile();
|
||||
return _client.sendEmailVerification();
|
||||
} else {
|
||||
return _sdk.sendEmailVerification();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> createAccount(String username, String password,
|
||||
{String displayName, String photoUrl}) async {
|
||||
if (useClient) {
|
||||
await _loadFile();
|
||||
return _client.createAccount(
|
||||
username,
|
||||
password,
|
||||
photoUrl: photoUrl,
|
||||
displayName: displayName,
|
||||
);
|
||||
} else {
|
||||
return _sdk.createAccount(
|
||||
username,
|
||||
password,
|
||||
photoUrl: photoUrl,
|
||||
displayName: displayName,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future loginCustomToken(String token) async {
|
||||
if (useClient) {
|
||||
return _client.loginCustomToken(token);
|
||||
} else {
|
||||
return _sdk.loginCustomToken(token);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future loginGoogle({String idToken, String accessToken}) async {
|
||||
if (useClient) {
|
||||
return _client.loginGoogle(
|
||||
idToken: idToken,
|
||||
accessToken: accessToken,
|
||||
);
|
||||
} else {
|
||||
return _sdk.loginGoogle(
|
||||
idToken: idToken,
|
||||
accessToken: accessToken,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import '../../classes/index.dart';
|
||||
import 'impl.dart';
|
||||
|
||||
class FBAuth implements FBAuthImpl {
|
||||
final FbApp app;
|
||||
|
||||
FBAuth(this.app);
|
||||
|
||||
@override
|
||||
Future<AuthUser> login(String username, String password) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> createAccount(String username, String password,
|
||||
{String displayName, String photoUrl}) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
@override
|
||||
Future logout() async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> currentUser() async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> startAsGuest() async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<AuthUser> onAuthChanged() {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
@override
|
||||
Future editInfo({String displayName, String photoUrl}) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
@override
|
||||
Future forgotPassword(String email) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
@override
|
||||
Future sendEmailVerification() async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
@override
|
||||
Future loginCustomToken(String token) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
@override
|
||||
Future loginGoogle({String idToken, String accessToken}) async {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
import 'package:firebase/firebase.dart';
|
||||
|
||||
import '../../classes/index.dart';
|
||||
import 'impl.dart';
|
||||
|
||||
class FBAuth implements FBAuthImpl {
|
||||
final FbApp app;
|
||||
final _auth = auth();
|
||||
|
||||
FBAuth(this.app);
|
||||
|
||||
Future _setPersistenceWeb(Auth _auth) async {
|
||||
// try {
|
||||
// var selectedPersistence = 'local';
|
||||
// await _auth.setPersistence(selectedPersistence);
|
||||
// } catch (e) {
|
||||
// print('_auth.setPersistence -> $e');
|
||||
// }
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> login(String username, String password) async {
|
||||
await _setPersistenceWeb(_auth);
|
||||
try {
|
||||
final _result =
|
||||
await _auth.signInWithEmailAndPassword(username, password);
|
||||
if (_result != null && _result?.user != null) {
|
||||
final _user = AuthUser(
|
||||
uid: _result.user.uid,
|
||||
displayName: _result.user.displayName,
|
||||
email: _result.user?.email,
|
||||
isAnonymous: _result.user.isAnonymous,
|
||||
isEmailVerified: _result.user.emailVerified,
|
||||
photoUrl: _result.user.photoURL,
|
||||
);
|
||||
return _user;
|
||||
}
|
||||
} catch (e) {
|
||||
print('FBAuthUtils -> _loginWeb -> $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> startAsGuest() async {
|
||||
await _setPersistenceWeb(_auth);
|
||||
try {
|
||||
final _result = await _auth.signInAnonymously();
|
||||
if (_result != null && _result?.user != null) {
|
||||
final _user = AuthUser(
|
||||
uid: _result.user.uid,
|
||||
displayName: _result.user.displayName,
|
||||
email: _result.user?.email,
|
||||
isAnonymous: _result.user.isAnonymous,
|
||||
isEmailVerified: _result.user.emailVerified,
|
||||
photoUrl: _result.user.photoURL,
|
||||
);
|
||||
return _user;
|
||||
}
|
||||
} catch (e) {
|
||||
print('FBAuthUtils -> startAsGuest -> $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future logout() async {
|
||||
try {
|
||||
await _auth.signOut();
|
||||
} catch (e) {
|
||||
print('FBAuthUtils -> logout -> $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<AuthUser> onAuthChanged() {
|
||||
return _auth.onAuthStateChanged.map((user) {
|
||||
if (user == null) return null;
|
||||
final _user = AuthUser(
|
||||
uid: user.uid,
|
||||
displayName: user.displayName,
|
||||
email: user?.email,
|
||||
isAnonymous: user.isAnonymous,
|
||||
isEmailVerified: user.emailVerified,
|
||||
photoUrl: user.photoURL,
|
||||
);
|
||||
return _user;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> currentUser() async {
|
||||
await _setPersistenceWeb(_auth);
|
||||
try {
|
||||
final _result = _auth.currentUser;
|
||||
if (_result != null) {
|
||||
final _user = AuthUser(
|
||||
uid: _result.uid,
|
||||
displayName: _result.displayName,
|
||||
email: _result?.email,
|
||||
isAnonymous: _result.isAnonymous,
|
||||
isEmailVerified: _result.emailVerified,
|
||||
photoUrl: _result.photoURL,
|
||||
);
|
||||
return _user;
|
||||
}
|
||||
} catch (e) {
|
||||
print('FBAuthUtils -> currentUser -> $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future editInfo({String displayName, String photoUrl}) async {
|
||||
final _user = _auth.currentUser;
|
||||
final _info = UserProfile();
|
||||
if (displayName != null) _info.displayName = displayName;
|
||||
if (photoUrl != null) _info.photoURL = photoUrl;
|
||||
try {
|
||||
await _user.updateProfile(_info);
|
||||
} catch (e) {
|
||||
throw 'Error editInfo -> $e';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future forgotPassword(String email) async {
|
||||
try {
|
||||
await _auth.sendPasswordResetEmail(email);
|
||||
} catch (e) {
|
||||
throw 'Error forgotPassword -> $e';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future sendEmailVerification() async {
|
||||
try {
|
||||
final _user = _auth.currentUser;
|
||||
await _user.sendEmailVerification();
|
||||
} catch (e) {
|
||||
throw 'Error sendEmailVerification -> $e';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> createAccount(String username, String password,
|
||||
{String displayName, String photoUrl}) async {
|
||||
UserCredential _user;
|
||||
try {
|
||||
_user = await _auth.createUserWithEmailAndPassword(username, password);
|
||||
if (_user != null) {
|
||||
await editInfo(displayName: displayName, photoUrl: photoUrl);
|
||||
}
|
||||
} catch (e) {}
|
||||
if (_user == null) {
|
||||
try {
|
||||
_user = await _auth.signInWithEmailAndPassword(username, password);
|
||||
} catch (err) {
|
||||
throw Exception(err);
|
||||
}
|
||||
}
|
||||
return await currentUser();
|
||||
}
|
||||
|
||||
@override
|
||||
Future loginCustomToken(String token) async {
|
||||
await _setPersistenceWeb(_auth);
|
||||
try {
|
||||
final _result = await _auth.signInAndRetrieveDataWithCustomToken(token);
|
||||
if (_result != null && _result?.user != null) {
|
||||
final _user = AuthUser(
|
||||
uid: _result.user.uid,
|
||||
displayName: _result.user.displayName,
|
||||
email: _result.user?.email,
|
||||
isAnonymous: _result.user.isAnonymous,
|
||||
isEmailVerified: _result.user.emailVerified,
|
||||
photoUrl: _result.user.photoURL,
|
||||
);
|
||||
return _user;
|
||||
}
|
||||
} catch (e) {
|
||||
print('FBAuthUtils -> loginCustomToken -> $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future loginGoogle({String idToken, String accessToken}) async {
|
||||
final _cred = GoogleAuthProvider.credential(idToken, accessToken);
|
||||
await _setPersistenceWeb(_auth);
|
||||
try {
|
||||
final _result = await _auth.signInWithCredential(_cred);
|
||||
if (_result != null && _result?.user != null) {
|
||||
final _user = AuthUser(
|
||||
uid: _result.user.uid,
|
||||
displayName: _result.user.displayName,
|
||||
email: _result.user?.email,
|
||||
isAnonymous: _result.user.isAnonymous,
|
||||
isEmailVerified: _result.user.emailVerified,
|
||||
photoUrl: _result.user.photoURL,
|
||||
);
|
||||
return _user;
|
||||
}
|
||||
} catch (e) {
|
||||
print('FBAuthUtils -> loginCustomToken -> $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
|
||||
import '../../classes/index.dart';
|
||||
import '../auth/impl.dart';
|
||||
|
||||
class FbSdk implements FBAuthImpl {
|
||||
final _auth = FirebaseAuth.instance;
|
||||
@override
|
||||
Future<AuthUser> login(String username, String password) async {
|
||||
try {
|
||||
final _result = await _auth.signInWithEmailAndPassword(
|
||||
email: username, password: password);
|
||||
if (_result != null && _result?.user != null) {
|
||||
final _user = AuthUser(
|
||||
uid: _result.user.uid,
|
||||
displayName: _result.user.displayName,
|
||||
email: _result.user?.email,
|
||||
isAnonymous: _result.user.isAnonymous,
|
||||
isEmailVerified: _result.user.isEmailVerified,
|
||||
photoUrl: _result.user.photoUrl,
|
||||
);
|
||||
return _user;
|
||||
}
|
||||
} catch (e) {
|
||||
print('FBAuthUtils -> _loginMobile -> $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<AuthUser> onAuthChanged() {
|
||||
return _auth.onAuthStateChanged.map((user) {
|
||||
if (user == null) return null;
|
||||
final _user = AuthUser(
|
||||
uid: user.uid,
|
||||
displayName: user.displayName,
|
||||
email: user?.email,
|
||||
isAnonymous: user.isAnonymous,
|
||||
isEmailVerified: user.isEmailVerified,
|
||||
photoUrl: user.photoUrl,
|
||||
);
|
||||
return _user;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> startAsGuest() async {
|
||||
final _result = await _auth.signInAnonymously();
|
||||
if (_result != null && _result?.user != null) {
|
||||
final _user = AuthUser(
|
||||
uid: _result.user.uid,
|
||||
displayName: _result.user.displayName,
|
||||
email: _result.user?.email,
|
||||
isAnonymous: _result.user.isAnonymous,
|
||||
isEmailVerified: _result.user.isEmailVerified,
|
||||
photoUrl: _result.user.photoUrl,
|
||||
);
|
||||
return _user;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future logout() async {
|
||||
try {
|
||||
await _auth.signOut();
|
||||
} catch (e) {
|
||||
print('FBAuthUtils -> logout -> $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> currentUser() async {
|
||||
try {
|
||||
final _result = await _auth.currentUser();
|
||||
if (_result != null) {
|
||||
final _user = AuthUser(
|
||||
uid: _result.uid,
|
||||
displayName: _result.displayName,
|
||||
email: _result?.email,
|
||||
isAnonymous: _result.isAnonymous,
|
||||
isEmailVerified: _result.isEmailVerified,
|
||||
photoUrl: _result.photoUrl,
|
||||
);
|
||||
return _user;
|
||||
}
|
||||
} catch (e) {
|
||||
print('FBAuthUtils -> currentUser -> $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future editInfo({String displayName, String photoUrl}) async {
|
||||
final _user = await _auth.currentUser();
|
||||
final _info = UserUpdateInfo();
|
||||
if (displayName != null) _info.displayName = displayName;
|
||||
if (photoUrl != null) _info.photoUrl = photoUrl;
|
||||
try {
|
||||
await _user.updateProfile(_info);
|
||||
} catch (e) {
|
||||
throw 'Error editInfo -> $e';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future forgotPassword(String email) async {
|
||||
try {
|
||||
await _auth.sendPasswordResetEmail(email: email);
|
||||
} catch (e) {
|
||||
throw 'Error forgotPassword -> $e';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future sendEmailVerification() async {
|
||||
try {
|
||||
final _user = await _auth.currentUser();
|
||||
await _user.sendEmailVerification();
|
||||
} catch (e) {
|
||||
throw 'Error sendEmailVerification -> $e';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> createAccount(String username, String password,
|
||||
{String displayName, String photoUrl}) async {
|
||||
AuthResult _user;
|
||||
try {
|
||||
_user = await _auth.createUserWithEmailAndPassword(
|
||||
email: username,
|
||||
password: password,
|
||||
);
|
||||
if (_user != null) {
|
||||
await editInfo(displayName: displayName, photoUrl: photoUrl);
|
||||
}
|
||||
} catch (e) {}
|
||||
if (_user == null) {
|
||||
try {
|
||||
_user = await _auth.signInWithEmailAndPassword(
|
||||
email: username,
|
||||
password: password,
|
||||
);
|
||||
} catch (err) {
|
||||
throw Exception(err);
|
||||
}
|
||||
}
|
||||
return await currentUser();
|
||||
}
|
||||
|
||||
@override
|
||||
FbApp get app => null;
|
||||
|
||||
@override
|
||||
Future loginGoogle({String idToken, String accessToken}) async {
|
||||
final _cred = GoogleAuthProvider.getCredential(
|
||||
idToken: idToken, accessToken: accessToken);
|
||||
try {
|
||||
final _result = await _auth.signInWithCredential(_cred);
|
||||
if (_result != null && _result?.user != null) {
|
||||
final _user = AuthUser(
|
||||
uid: _result.user.uid,
|
||||
displayName: _result.user.displayName,
|
||||
email: _result.user?.email,
|
||||
isAnonymous: _result.user.isAnonymous,
|
||||
isEmailVerified: _result.user.isEmailVerified,
|
||||
photoUrl: _result.user.photoUrl,
|
||||
);
|
||||
return _user;
|
||||
}
|
||||
} catch (e) {
|
||||
print('FBAuthUtils -> loginGoogle -> $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future loginCustomToken(String token) async {
|
||||
try {
|
||||
final _result = await _auth.signInWithCustomToken(token: token);
|
||||
if (_result != null && _result?.user != null) {
|
||||
final _user = AuthUser(
|
||||
uid: _result.user.uid,
|
||||
displayName: _result.user.displayName,
|
||||
email: _result.user?.email,
|
||||
isAnonymous: _result.user.isAnonymous,
|
||||
isEmailVerified: _result.user.isEmailVerified,
|
||||
photoUrl: _result.user.photoUrl,
|
||||
);
|
||||
return _user;
|
||||
}
|
||||
} catch (e) {
|
||||
print('FBAuthUtils -> loginCustomToken -> $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../../classes/index.dart';
|
||||
import '../auth/impl.dart';
|
||||
import 'helpers/index.dart';
|
||||
|
||||
class FbClient implements FBAuthImpl {
|
||||
FbClient(
|
||||
this.app, {
|
||||
@required this.onSave,
|
||||
@required this.onLoad,
|
||||
}) {
|
||||
_onAuthChanged = StreamController<AuthUser>();
|
||||
}
|
||||
|
||||
StreamController<AuthUser> _onAuthChanged;
|
||||
|
||||
@override
|
||||
final FbApp app;
|
||||
|
||||
@override
|
||||
Future<AuthUser> createAccount(String username, String password,
|
||||
{String displayName, String photoUrl}) async {
|
||||
final result = await http.post(
|
||||
'https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${app.apiKey}',
|
||||
body: json.encode(
|
||||
{
|
||||
"email": username,
|
||||
"password": password,
|
||||
"returnSecureToken": true,
|
||||
},
|
||||
));
|
||||
FirestoreJsonAccessToken token = await _saveToken(result);
|
||||
await editInfo(displayName: displayName, photoUrl: photoUrl);
|
||||
token = await _loadToken();
|
||||
return _getUser(token);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> currentUser() async {
|
||||
FirestoreJsonAccessToken token = await _loadToken();
|
||||
if (token != null) {
|
||||
var result = await http.post(
|
||||
'https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${app.apiKey}',
|
||||
body: json.encode({
|
||||
"idToken": token?.idToken,
|
||||
"returnSecureToken": true,
|
||||
}),
|
||||
);
|
||||
token = await _saveToken(result);
|
||||
return _getUser(token);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future editInfo({String displayName, String photoUrl}) async {
|
||||
FirestoreJsonAccessToken token = await _loadToken();
|
||||
final result = await http.post(
|
||||
'https://identitytoolkit.googleapis.com/v1/accounts:update?key=${app.apiKey}',
|
||||
body: json.encode({
|
||||
"idToken": token?.idToken,
|
||||
if (displayName != null) ...{
|
||||
'displayName': displayName,
|
||||
},
|
||||
if (photoUrl != null) ...{
|
||||
'photoUrl': photoUrl,
|
||||
},
|
||||
"deleteAttribute": [
|
||||
if (displayName == null) 'DISPLAY_NAME',
|
||||
if (photoUrl == null) 'PHOTO_URL',
|
||||
],
|
||||
"returnSecureToken": true,
|
||||
}),
|
||||
);
|
||||
await _saveToken(result);
|
||||
}
|
||||
|
||||
@override
|
||||
Future forgotPassword(String email) async {
|
||||
final _url =
|
||||
'https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=${app.apiKey}';
|
||||
|
||||
var result = await http.post(
|
||||
_url,
|
||||
body: json.encode({
|
||||
'requestType': 'PASSWORD_RESET',
|
||||
"identifier": email,
|
||||
}),
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> login(String username, String password) async {
|
||||
final result = await http.post(
|
||||
'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${app.apiKey}',
|
||||
body: json.encode({
|
||||
"email": username,
|
||||
"password": password,
|
||||
"returnSecureToken": true,
|
||||
}),
|
||||
);
|
||||
final token = await _saveToken(result);
|
||||
return _getUser(token);
|
||||
}
|
||||
|
||||
@override
|
||||
Future logout() async {
|
||||
onSave(null);
|
||||
_onAuthChanged.add(null);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<AuthUser> onAuthChanged() {
|
||||
return _onAuthChanged.stream;
|
||||
}
|
||||
|
||||
@override
|
||||
Future sendEmailVerification() async {
|
||||
FirestoreJsonAccessToken token = await _loadToken();
|
||||
var result = await http.post(
|
||||
'https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=${app.apiKey}',
|
||||
body: json.encode({
|
||||
"idToken": token?.idToken,
|
||||
"requestType": 'VERIFY_EMAIL',
|
||||
}),
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AuthUser> startAsGuest() async {
|
||||
final result = await http.post(
|
||||
'https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${app.apiKey}',
|
||||
body: json.encode({
|
||||
"returnSecureToken": true,
|
||||
}),
|
||||
);
|
||||
FirestoreJsonAccessToken token = await _saveToken(result);
|
||||
return _getUser(token);
|
||||
}
|
||||
|
||||
final Future<Map<String, dynamic>> Function() onLoad;
|
||||
|
||||
final Future Function(Map<String, dynamic>) onSave;
|
||||
|
||||
Future<FirestoreJsonAccessToken> _saveToken(http.Response result) async {
|
||||
final _data = json.decode(result.body);
|
||||
final token = FirestoreJsonAccessToken(_data, DateTime.now());
|
||||
await onSave(_data);
|
||||
return token;
|
||||
}
|
||||
|
||||
Future<AuthUser> _getUser(FirestoreJsonAccessToken token) async {
|
||||
http.Response result = await http.post(
|
||||
'https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${app.apiKey}',
|
||||
body: json.encode({
|
||||
"idToken": token.idToken,
|
||||
"returnSecureToken": true,
|
||||
}));
|
||||
final _users = List.from(json.decode(result.body)['users']);
|
||||
if (result != null)
|
||||
for (var item in _users) {
|
||||
final _user = FirebaseUser(item, token.idToken);
|
||||
if (_user.uid == token.localId) {
|
||||
final _auth = AuthUser(
|
||||
displayName: _user?.displayName,
|
||||
email: _user?.email,
|
||||
isAnonymous: _user?.isAnonymous ?? true,
|
||||
isEmailVerified: _user?.isEmailVerified ?? false,
|
||||
photoUrl: _user.photoUrl,
|
||||
uid: _user?.uid,
|
||||
);
|
||||
_onAuthChanged.add(_auth);
|
||||
return _auth;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<FirestoreJsonAccessToken> _loadToken() async {
|
||||
final _data = await onLoad();
|
||||
if (_data != null) {
|
||||
final token = FirestoreJsonAccessToken(_data, DateTime.now());
|
||||
return token;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future loginCustomToken(String token) {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
|
||||
@override
|
||||
Future loginGoogle({String idToken, String accessToken}) {
|
||||
throw 'Platform Not Supported';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export 'token.dart';
|
||||
export 'user.dart';
|
||||
@@ -0,0 +1,26 @@
|
||||
class FirestoreJsonAccessToken {
|
||||
FirestoreJsonAccessToken(this.json, this.createdAt);
|
||||
|
||||
final Map<String, dynamic> json;
|
||||
|
||||
String get refreshToken => json["refresh_token"];
|
||||
|
||||
final DateTime createdAt;
|
||||
|
||||
DateTime get expiresAt =>
|
||||
createdAt.add(new Duration(seconds: expiresInSeconds));
|
||||
|
||||
String get displayName => json['displayName'] as String;
|
||||
|
||||
String get email => json['email'] as String;
|
||||
|
||||
String get kind => json['kind'] as String;
|
||||
|
||||
String get idToken => json['idToken'];
|
||||
|
||||
String get localId => json['localId'] as String;
|
||||
|
||||
int get expiresInSeconds => int.tryParse(json["expiresIn"]);
|
||||
|
||||
bool get emailVerified => json['emailVerified'];
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
class FirebaseUser {
|
||||
FirebaseUser(this.json, this.idToken);
|
||||
|
||||
@override
|
||||
final Map<String, dynamic> json;
|
||||
|
||||
final String idToken;
|
||||
|
||||
String get displayName => json['displayName'];
|
||||
|
||||
String get email => json['email'];
|
||||
|
||||
String get photoUrl => json['photoUrl'];
|
||||
|
||||
String get uid => json['localId'];
|
||||
|
||||
bool get registered => json['registered'] ?? false;
|
||||
|
||||
List<ProviderInfo> get providerUserInfo {
|
||||
if (json['providerUserInfo'] == null) return null;
|
||||
return List.from(json['providerUserInfo']).map((i) {
|
||||
final _data = i as Map<String, dynamic>;
|
||||
return ProviderInfo(_data['providerId'], _data['federatedId']);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
bool get isAnonymous => email == null || email.isEmpty;
|
||||
|
||||
bool get isEmailVerified => json['emailVerified'];
|
||||
|
||||
String get passwordHash => json['passwordHash'];
|
||||
|
||||
double get passwordUpdatedAt => json['passwordUpdatedAt'];
|
||||
|
||||
DateTime get validSince => json['validSince'];
|
||||
|
||||
bool get disabled => json['disabled'];
|
||||
|
||||
DateTime get lastLoginAt => json['lastLoginAt'];
|
||||
|
||||
DateTime get createdAt => json['createdAt'];
|
||||
|
||||
bool get customAuth => json['customAuth'];
|
||||
}
|
||||
|
||||
class ProviderInfo {
|
||||
ProviderInfo(this.providerId, this.federatedId);
|
||||
|
||||
final String providerId, federatedId;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class PathUtils {
|
||||
PathUtils._();
|
||||
|
||||
static Future<Directory> getDocumentDir() async {
|
||||
if (Platform.isMacOS || Platform.isLinux) {
|
||||
return Directory('${Platform.environment['HOME']}/.config');
|
||||
} else if (Platform.isWindows) {
|
||||
return Directory('${Platform.environment['UserProfile']}\\.config');
|
||||
}
|
||||
return await getApplicationDocumentsDirectory();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export 'data/blocs/blocs.dart';
|
||||
export 'data/classes/index.dart';
|
||||
export 'data/services/auth/auth.dart';
|
||||
export 'data/services/rest_api/client.dart';
|
||||
export 'data/services/rest_api/helpers/index.dart';
|
||||
Reference in New Issue
Block a user