I need to make the users UID the same as the documents id.
ex:
In [Authentication], I have the user with the following info:
email: [email protected]
UID: U8EZAjrCWQRvll6CVmI6OpGZwcH3
In [Firestore database], I have a user collection.
In the user collection, I have a document for each user.
I would like to have the document id be the same as the user id.
is this possible?
Below is the snip I have for creating users in [Authentication] and [Firestore database] user collection::
class FirebaseAuthProvider implements AuthProvider {
@override
Future<void> initialize() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
}
@override
Future<AuthUser> createUser({
required String email,
required String password,
}) async {
try {
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: email,
password: password,
);
final user = currentUser;
if (user != null) {
return user;
} else {
throw UserNotLoggedInAuthException();
}
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
throw WeakPasswordAuthException();
} else if (e.code == 'email-already-in-use') {
throw EmailAlreadyInUseAuthException();
} else if (e.code == 'invalid-email') {
throw InvalidEmailAuthException();
} else {
throw GenericAuthException();
}
} catch (_) {
throw GenericAuthException();
}
}
}
Below is my FirebaseCloudStorage class
class FirebaseCloudStorage {
final user = FirebaseFirestore.instance.collection('user');
Future<CloudUser> createNewUser({
required String userId,
required String userState,
required String userImage,
required String userFirstName,
required String userLastName,
required String userCellNumber,
required String userCity,
required String userAreaCode,
required String userAddress,
required String userEmail,
}) async {
final document = await user.add({
userIdColumn: userId,
userStateColumn: userState,
userImageColumn: userImage,
userFirstNameColumn: userFirstName,
userLastNameColumn: userLastName,
userCellNumberColumn: userCellNumber,
userCityColumn: userCity,
userAreaCodeColumn: userAreaCode,
userAddressColumn: userAddress,
userEmailColumn: userEmail,
});
final fetchedUser = await document.get();
return CloudUser(
documentId: fetchedUser.id,
userId: userId,
userState: userState,
userImage: userImage,
userFirstName: userFirstName,
userLastName: userLastName,
userCellNumber: userCellNumber,
userCity: userCity,
userAreaCode: userAreaCode,
userAddress: userAddress,
userEmail: userEmail,
);
}
// singleton
static final FirebaseCloudStorage _shared =
FirebaseCloudStorage._sharedInstance();
FirebaseCloudStorage._sharedInstance();
factory FirebaseCloudStorage() => _shared;
}
Below is the sign up screen button that kicks off all the creation
Future createUserAccount() async {
if (_photo == null) return;
try {
setState(() {
_isLoading = true;
});
await AuthService.firebase().createUser(
email: _email.text,
password: _password.text,
// displayName: _userFirstName.text, // not working
);
final userId = AuthService.firebase().currentUser?.id;
final destination = 'user-profile-image/$userId';
final ref = FirebaseStorage.instance.ref(destination);
await ref.putFile(_photo!);
imageUrl = await ref.getDownloadURL();
_userService.createNewUser(
userId: userId as String,
userState: 'new',
userImage: imageUrl as String,
userFirstName: _userFirstName.text,
userLastName: _userLastName.text,
userCellNumber: _userCellphoneNumber.text,
userCity: _userCity.text,
userAreaCode: _userAreaCode.text,
userAddress: _userAddress.text,
userEmail: _email.text,
);
setState(() {
_isLoading = false;
});
AuthService.firebase().sendEmailVerification();
Navigator.of(context).pushNamed(verifyEmailRoute);
} on WeakPasswordAuthException {
await showErrorDialog(
context,
'Weak password',
);
} on EmailAlreadyInUseAuthException {
await showErrorDialog(
context,
'Email is already in use',
);
} on InvalidEmailAuthException {
await showErrorDialog(
context,
'This is an invalid email address',
);
} on GenericAuthException {
await showErrorDialog(
context,
'Failed to register',
);
}
}
2
Answers
You can use a custom id for a document by using
set
instead ofadd
and specifying the already existing user identifier. So in yourcreateNewUser
function you can do it like:Note: It might be a better solution to maintain your own user collection from a trusted environment on the server side and not from the client. For example you can use Firebase Authentication triggers to add / delete / modify user data whenever there is a change, for example a new user is signed up. This way you don’t have to allow write operations to your user collection from the client.
You can use an onCreate trigger on an authentication event.
If you are using cloud functions you can use the following code to create a new document in your user collection when a new authentication entry is created:
Information about triggers: https://firebase.google.com/docs/functions/auth-events