auth phone and re auth phone
This commit is contained in:
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user