first steps for auth in staff app
This commit is contained in:
@@ -1,34 +1,113 @@
|
||||
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||
import 'package:krow_domain/krow_domain.dart' as domain;
|
||||
import '../../domain/repositories/auth_repository_interface.dart';
|
||||
|
||||
/// Implementation of [AuthRepositoryInterface].
|
||||
class AuthRepositoryImpl implements AuthRepositoryInterface {
|
||||
final AuthRepositoryMock mock;
|
||||
final firebase.FirebaseAuth _firebaseAuth;
|
||||
final dc.ExampleConnector _dataConnect;
|
||||
|
||||
AuthRepositoryImpl({required this.mock});
|
||||
AuthRepositoryImpl({
|
||||
required firebase.FirebaseAuth firebaseAuth,
|
||||
required dc.ExampleConnector dataConnect,
|
||||
}) : _firebaseAuth = firebaseAuth,
|
||||
_dataConnect = dataConnect;
|
||||
|
||||
@override
|
||||
Stream<User?> get currentUser => mock.currentUser;
|
||||
Stream<domain.User?> get currentUser => _firebaseAuth
|
||||
.authStateChanges()
|
||||
.map((firebaseUser) {
|
||||
if (firebaseUser == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return domain.User(
|
||||
id: firebaseUser.uid,
|
||||
email: firebaseUser.email ?? '',
|
||||
phone: firebaseUser.phoneNumber,
|
||||
role: 'staff',
|
||||
);
|
||||
});
|
||||
|
||||
/// Signs in with a phone number and returns a verification ID.
|
||||
@override
|
||||
Future<String?> signInWithPhone({required String phoneNumber}) {
|
||||
return mock.signInWithPhone(phoneNumber);
|
||||
Future<String?> signInWithPhone({required String phoneNumber}) async {
|
||||
final completer = Completer<String?>();
|
||||
|
||||
await _firebaseAuth.verifyPhoneNumber(
|
||||
phoneNumber: phoneNumber,
|
||||
verificationCompleted: (_) {},
|
||||
verificationFailed: (e) {
|
||||
if (!completer.isCompleted) {
|
||||
completer.completeError(
|
||||
Exception(e.message ?? 'Phone verification failed.'),
|
||||
);
|
||||
}
|
||||
},
|
||||
codeSent: (verificationId, _) {
|
||||
if (!completer.isCompleted) {
|
||||
completer.complete(verificationId);
|
||||
}
|
||||
},
|
||||
codeAutoRetrievalTimeout: (verificationId) {
|
||||
if (!completer.isCompleted) {
|
||||
completer.complete(verificationId);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
/// Signs out the current user.
|
||||
@override
|
||||
Future<void> signOut() {
|
||||
return mock.signOut();
|
||||
return _firebaseAuth.signOut();
|
||||
}
|
||||
|
||||
/// Verifies an OTP code and returns the authenticated user.
|
||||
@override
|
||||
Future<User?> verifyOtp({
|
||||
Future<domain.User?> verifyOtp({
|
||||
required String verificationId,
|
||||
required String smsCode,
|
||||
}) {
|
||||
return mock.verifyOtp(verificationId, smsCode);
|
||||
}) async {
|
||||
final credential = firebase.PhoneAuthProvider.credential(
|
||||
verificationId: verificationId,
|
||||
smsCode: smsCode,
|
||||
);
|
||||
final userCredential = await _firebaseAuth.signInWithCredential(credential);
|
||||
final firebaseUser = userCredential.user;
|
||||
if (firebaseUser == null) {
|
||||
throw Exception('Phone verification failed, no Firebase user received.');
|
||||
}
|
||||
|
||||
final response = await _dataConnect.getUserById(
|
||||
id: firebaseUser.uid,
|
||||
).execute();
|
||||
final user = response.data?.user;
|
||||
if (user == null) {
|
||||
await _firebaseAuth.signOut();
|
||||
throw Exception('Authenticated user profile not found in database.');
|
||||
}
|
||||
if (user.userRole != 'STAFF') {
|
||||
await _firebaseAuth.signOut();
|
||||
throw Exception('User is not authorized for this app.');
|
||||
}
|
||||
|
||||
final email = user.email ?? '';
|
||||
if (email.isEmpty) {
|
||||
await _firebaseAuth.signOut();
|
||||
throw Exception('User email is missing in profile data.');
|
||||
}
|
||||
|
||||
return domain.User(
|
||||
id: user.id,
|
||||
email: email,
|
||||
phone: firebaseUser.phoneNumber,
|
||||
role: user.role.stringValue,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ library staff_authentication;
|
||||
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
||||
import 'package:staff_authentication/src/data/repositories_impl/auth_repository_impl.dart';
|
||||
import 'package:staff_authentication/src/domain/repositories/auth_repository_interface.dart';
|
||||
import 'package:staff_authentication/src/domain/usecases/sign_in_with_phone_usecase.dart';
|
||||
@@ -28,7 +29,10 @@ class StaffAuthenticationModule extends Module {
|
||||
void binds(Injector i) {
|
||||
// Repositories
|
||||
i.addLazySingleton<AuthRepositoryInterface>(
|
||||
() => AuthRepositoryImpl(mock: i.get<AuthRepositoryMock>()),
|
||||
() => AuthRepositoryImpl(
|
||||
firebaseAuth: firebase.FirebaseAuth.instance,
|
||||
dataConnect: ExampleConnector.instance,
|
||||
),
|
||||
);
|
||||
|
||||
// UseCases
|
||||
|
||||
Reference in New Issue
Block a user