auth phone and re auth phone

This commit is contained in:
Felipe
2024-03-12 20:02:00 -05:00
parent 13896f2b6d
commit 312cc3d863
16 changed files with 1049 additions and 178 deletions
@@ -167,6 +167,14 @@ class FirebaseUserRepository implements UserRepository {
await _firebaseAuth.currentUser!.updateEmail(email);
await _firebaseAuth.currentUser!.updatePassword(password);
final user = await getMyUser(_firebaseAuth.currentUser!.uid);
if (user == null) {
return "user-not-found";
}
final newUser = user.copyWith(email: email);
await updateUserInfo(newUser);
return null;
} catch (e) {
if (e is FirebaseAuthException && e.code == 'requires-recent-login') {
@@ -181,6 +189,95 @@ class FirebaseUserRepository implements UserRepository {
}
}
@override
addPhoneAuthCredential(String password, String phoneNumber,
{required Future<void> Function(FirebaseAuthException) verificationFailed,
required Future<void> Function(String) codeSent,
required Future<void> Function(String) codeAutoRetrievalTimeout}) async {
await _firebaseAuth.verifyPhoneNumber(
phoneNumber: phoneNumber,
timeout: const Duration(seconds: 60),
verificationCompleted: (AuthCredential authCredential) async {
// La verificación se completó automáticamente.
// TODO: Revisar si es necesario.
},
verificationFailed: (FirebaseAuthException authException) async {
// La verificación falló.
// throw authException;
log('verificationFailed: $authException');
await verificationFailed(authException);
},
codeAutoRetrievalTimeout: (String verificationId) async {
// Tiempo de espera agotado para la recuperación automática del código.
// throw 'timeout';
log(verificationId);
await codeAutoRetrievalTimeout(verificationId);
},
codeSent: (String verificationId, int? resendToken) async {
await codeSent(verificationId);
},
);
}
@override
Future<bool> linkWithOTP(
String phoneNumber, String verificationId, String code) async {
try {
var phoneAuthCredential = PhoneAuthProvider.credential(
verificationId: verificationId, smsCode: code);
User? userAuth = FirebaseAuth.instance.currentUser;
if (userAuth == null) {
throw 'User not found';
}
final user = await getMyUser(_firebaseAuth.currentUser!.uid);
if (user == null) {
throw "user-not-found";
}
await userAuth.linkWithCredential(phoneAuthCredential);
final newUser = user.copyWith(phone: phoneNumber);
await updateUserInfo(newUser);
return true;
} catch (e) {
if (e is FirebaseAuthException) {
if (e.code == 'invalid-verification-code') {
return false;
} else {
rethrow;
}
} else {
rethrow;
}
}
}
@override
Future<UpdatePassworErros?> updatePassword(
String password, String newPassword) async {
try {
User? user = FirebaseAuth.instance.currentUser;
if (user == null) {
return UpdatePassworErros.userNotFound;
}
// Verificar la autenticación reciente
await user.reauthenticateWithCredential(EmailAuthProvider.credential(
email: user.email!,
password: password,
));
await _firebaseAuth.currentUser!.updatePassword(newPassword);
return null;
} catch (e) {
log(e.toString());
return UpdatePassworErros.unknown;
}
}
// Sign out
@override
Future<void> logOut() async {
@@ -1,3 +1,5 @@
import 'package:firebase_auth/firebase_auth.dart';
import '../../user_repository.dart';
abstract class UserRepository {
@@ -8,6 +10,9 @@ abstract class UserRepository {
Future<String?> addEmailAndPassword(String email, String password);
Future<UpdatePassworErros?> updatePassword(
String password, String newPassword);
Future<void> logOut();
Future<MyUser> signUp(MyUser myUser, String password);
@@ -16,6 +21,17 @@ abstract class UserRepository {
Future<bool> verifyOTP(String code);
Future<void> addPhoneAuthCredential(String password, String phoneNumber,
{
required Future<void> Function(FirebaseAuthException) verificationFailed,
required Future<void> Function(String) codeSent,
required Future<void> Function(String) codeAutoRetrievalTimeout
});
Future<bool> linkWithOTP(
String phoneNumber, String verificationId, String code);
Future<void> resetPassword(String email);
Future<void> setUserData(MyUser user);
@@ -28,3 +44,5 @@ abstract class UserRepository {
Future<void> createUser(MyUser myUser);
}
enum UpdatePassworErros { credentialsWrong, userNotFound, unknown }
@@ -0,0 +1,76 @@
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
class PhoneVerificationService {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Stream<PhoneAuthEvent> verifyPhoneNumber(String phoneNumber) async* {
final StreamController<PhoneAuthEvent> phoneAuthController =
StreamController<PhoneAuthEvent>();
_firebaseAuth.verifyPhoneNumber(
phoneNumber: phoneNumber,
timeout: const Duration(seconds: 60),
verificationCompleted: (AuthCredential authCredential) async {
phoneAuthController
.add(PhoneAuthEvent.verificationCompleted(authCredential));
},
verificationFailed: (FirebaseAuthException authException) async {
phoneAuthController
.add(PhoneAuthEvent.verificationFailed(authException));
phoneAuthController.close();
},
codeAutoRetrievalTimeout: (String verificationId) async {
phoneAuthController
.add(PhoneAuthEvent.codeAutoRetrievalTimeout(verificationId));
},
codeSent: (String verificationId, int? resendToken) async {
phoneAuthController
.add(PhoneAuthEvent.codeSent(verificationId, resendToken));
},
);
await for (PhoneAuthEvent event in phoneAuthController.stream) {
yield event;
if (event.type == PhoneAuthEventType.verificationFailed) {
await phoneAuthController.close();
break;
}
}
}
}
enum PhoneAuthEventType {
verificationCompleted,
verificationFailed,
codeAutoRetrievalTimeout,
codeSent,
}
class PhoneAuthEvent {
final PhoneAuthEventType type;
final dynamic data;
PhoneAuthEvent(this.type, this.data);
static PhoneAuthEvent verificationCompleted(AuthCredential authCredential) {
return PhoneAuthEvent(
PhoneAuthEventType.verificationCompleted, authCredential);
}
static PhoneAuthEvent verificationFailed(
FirebaseAuthException authException) {
return PhoneAuthEvent(PhoneAuthEventType.verificationFailed, authException);
}
static PhoneAuthEvent codeAutoRetrievalTimeout(String verificationId) {
return PhoneAuthEvent(
PhoneAuthEventType.codeAutoRetrievalTimeout, verificationId);
}
static PhoneAuthEvent codeSent(String verificationId, int? resendToken) {
return PhoneAuthEvent(PhoneAuthEventType.codeSent,
{'verificationId': verificationId, 'resendToken': resendToken});
}
}
@@ -2,5 +2,6 @@ library user_repository;
export 'src/models/models.dart';
export 'src/entities/entities.dart';
export 'src/services/phone_verification_service.dart';
export 'src/repositories/user_repo.dart';
export 'src/repositories/firebase_user_repository.dart';