validation userrole

This commit is contained in:
José Salazar
2026-01-22 16:04:10 -05:00
parent c341638d73
commit 6e8578c3d7

View File

@@ -1,5 +1,5 @@
import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_auth/firebase_auth.dart' as firebase;
import 'package:krow_data_connect/krow_data_connect.dart'; import 'package:krow_data_connect/krow_data_connect.dart' as dc;
import 'package:krow_domain/krow_domain.dart' as domain; import 'package:krow_domain/krow_domain.dart' as domain;
import '../../domain/repositories/auth_repository_interface.dart'; import '../../domain/repositories/auth_repository_interface.dart';
@@ -8,15 +8,15 @@ import '../../domain/repositories/auth_repository_interface.dart';
/// This implementation integrates with Firebase Authentication for user /// This implementation integrates with Firebase Authentication for user
/// identity management and Krow's Data Connect SDK for storing user profile data. /// identity management and Krow's Data Connect SDK for storing user profile data.
class AuthRepositoryImpl implements AuthRepositoryInterface { class AuthRepositoryImpl implements AuthRepositoryInterface {
final FirebaseAuth _firebaseAuth; final firebase.FirebaseAuth _firebaseAuth;
final ExampleConnector _dataConnect; final dc.ExampleConnector _dataConnect;
/// Creates an [AuthRepositoryImpl] with the real dependencies. /// Creates an [AuthRepositoryImpl] with the real dependencies.
AuthRepositoryImpl({ AuthRepositoryImpl({
required FirebaseAuth firebaseAuth, required firebase.FirebaseAuth firebaseAuth,
required ExampleConnector dataConnect, required dc.ExampleConnector dataConnect,
}) : _firebaseAuth = firebaseAuth, }) : _firebaseAuth = firebaseAuth,
_dataConnect = dataConnect; _dataConnect = dataConnect;
@override @override
Future<domain.User> signInWithEmail({ Future<domain.User> signInWithEmail({
@@ -34,38 +34,19 @@ class AuthRepositoryImpl implements AuthRepositoryInterface {
throw Exception('Sign-in failed, no Firebase user received.'); throw Exception('Sign-in failed, no Firebase user received.');
} }
final response = await _dataConnect.getUserById( return _getUserProfile(
id: firebaseUser.uid, firebaseUserId: firebaseUser.uid,
).execute(); fallbackEmail: firebaseUser.email ?? email,
final user = response.data?.user;
if (user == null) {
await _firebaseAuth.signOut();
throw Exception('Authenticated user profile not found in database.');
}
if (user.userRole != 'BUSINESS') {
await _firebaseAuth.signOut();
throw Exception('User is not authorized for this app.');
}
final resolvedEmail = user.email ?? firebaseUser.email ?? email;
if (resolvedEmail.isEmpty) {
throw Exception('User email is missing in profile data.');
}
return domain.User(
id: user.id,
email: resolvedEmail,
role: user.role.stringValue,
); );
//TO-DO: validate that user is business role and has business account
} on firebase.FirebaseAuthException catch (e) { } on firebase.FirebaseAuthException catch (e) {
if (e.code == 'invalid-credential' || e.code == 'wrong-password') { if (e.code == 'invalid-credential' || e.code == 'wrong-password') {
throw Exception('Incorrect email or password.'); throw Exception('Incorrect email or password.');
} else { } else {
throw Exception('Authentication error: ${e.message}'); throw Exception('Authentication error: ${e.message}');
} }
} on Exception catch (e) {
throw e;
} catch (e) { } catch (e) {
throw Exception('Failed to sign in and fetch user data: ${e.toString()}'); throw Exception('Failed to sign in and fetch user data: ${e.toString()}');
} }
@@ -91,25 +72,23 @@ class AuthRepositoryImpl implements AuthRepositoryInterface {
// Client-specific business logic: // Client-specific business logic:
// 1. Create a `Business` entity. // 1. Create a `Business` entity.
// 2. Create a `User` entity associated with the business. // 2. Create a `User` entity associated with the business.
final createBusinessResponse = await _dataConnect final createBusinessResponse = await _dataConnect.createBusiness(
.createBusiness( businessName: companyName,
businessName: companyName, userId: firebaseUser.uid,
userId: firebaseUser.uid, rateGroup: dc.BusinessRateGroup.STANDARD,
rateGroup: BusinessRateGroup.STANDARD, status: dc.BusinessStatus.PENDING,
status: BusinessStatus.PENDING, ).execute();
)
.execute();
final businessData = createBusinessResponse.data?.business_insert; final businessData = createBusinessResponse.data?.business_insert;
if (businessData == null) { if (businessData == null) {
await firebaseUser.delete(); // Rollback if business creation fails await firebaseUser.delete(); // Rollback if business creation fails
throw Exception( throw Exception('Business creation failed after Firebase user registration.');
'Business creation failed after Firebase user registration.',
);
} }
final createUserResponse = await _dataConnect final createUserResponse = await _dataConnect.createUser(
.createUser(id: firebaseUser.uid, role: UserBaseRole.USER) id: firebaseUser.uid,
role: dc.UserBaseRole.USER,
)
.email(email) .email(email)
.userRole('BUSINESS') .userRole('BUSINESS')
.execute(); .execute();
@@ -118,16 +97,15 @@ class AuthRepositoryImpl implements AuthRepositoryInterface {
if (newUserData == null) { if (newUserData == null) {
await firebaseUser.delete(); // Rollback if user profile creation fails await firebaseUser.delete(); // Rollback if user profile creation fails
// TO-DO: Also delete the created Business if this fails // TO-DO: Also delete the created Business if this fails
throw Exception( throw Exception('User profile creation failed after Firebase user registration.');
'User profile creation failed after Firebase user registration.',
);
} }
return _getUserProfile( return _getUserProfile(
firebaseUserId: firebaseUser.uid, firebaseUserId: firebaseUser.uid,
fallbackEmail: firebaseUser.email ?? email, fallbackEmail: firebaseUser.email ?? email,
); );
} on FirebaseAuthException catch (e) {
} on firebase.FirebaseAuthException catch (e) {
if (e.code == 'weak-password') { if (e.code == 'weak-password') {
throw Exception('The password provided is too weak.'); throw Exception('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') { } else if (e.code == 'email-already-in-use') {
@@ -136,9 +114,7 @@ class AuthRepositoryImpl implements AuthRepositoryInterface {
throw Exception('Sign-up error: ${e.message}'); throw Exception('Sign-up error: ${e.message}');
} }
} catch (e) { } catch (e) {
throw Exception( throw Exception('Failed to sign up and create user data: ${e.toString()}');
'Failed to sign up and create user data: ${e.toString()}',
);
} }
} }
@@ -153,18 +129,14 @@ class AuthRepositoryImpl implements AuthRepositoryInterface {
@override @override
Future<domain.User> signInWithSocial({required String provider}) { Future<domain.User> signInWithSocial({required String provider}) {
throw UnimplementedError( throw UnimplementedError('Social authentication with $provider is not yet implemented.');
'Social authentication with $provider is not yet implemented.',
);
} }
Future<domain.User> _getUserProfile({ Future<domain.User> _getUserProfile({
required String firebaseUserId, required String firebaseUserId,
required String? fallbackEmail, required String? fallbackEmail,
}) async { }) async {
final response = await _dataConnect final response = await _dataConnect.getUserById(id: firebaseUserId).execute();
.getUserById(id: firebaseUserId)
.execute();
final user = response.data?.user; final user = response.data?.user;
if (user == null) { if (user == null) {
throw Exception('Authenticated user profile not found in database.'); throw Exception('Authenticated user profile not found in database.');
@@ -175,6 +147,10 @@ class AuthRepositoryImpl implements AuthRepositoryInterface {
throw Exception('User email is missing in profile data.'); throw Exception('User email is missing in profile data.');
} }
return domain.User(id: user.id, email: email, role: user.role.stringValue); return domain.User(
id: user.id,
email: email,
role: user.role.stringValue,
);
} }
} }