diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart b/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart index d8935c46..00b33378 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/data/repositories_impl/auth_repository_impl.dart @@ -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 get currentUser => mock.currentUser; + Stream 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 signInWithPhone({required String phoneNumber}) { - return mock.signInWithPhone(phoneNumber); + Future signInWithPhone({required String phoneNumber}) async { + final completer = Completer(); + + 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 signOut() { - return mock.signOut(); + return _firebaseAuth.signOut(); } /// Verifies an OTP code and returns the authenticated user. @override - Future verifyOtp({ + Future 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, + ); } } diff --git a/apps/mobile/packages/features/staff/authentication/lib/staff_authentication.dart b/apps/mobile/packages/features/staff/authentication/lib/staff_authentication.dart index 2c272187..ab9bc99a 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/staff_authentication.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/staff_authentication.dart @@ -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( - () => AuthRepositoryImpl(mock: i.get()), + () => AuthRepositoryImpl( + firebaseAuth: firebase.FirebaseAuth.instance, + dataConnect: ExampleConnector.instance, + ), ); // UseCases