The above code will give me null in the field since my app uses password authentication - firebase

void _addMessage(String value) async {
final user = FirebaseAuth.instance.currentUser;
if (user != null) {
await FirebaseFirestore.instance.collection("interest_chat").add({
'author': user.displayName ?? "Anonymous",
'author_id': user.uid,
'timestamp': Timestamp.now().millisecondsSinceEpoch,
'value': value,
});
}
}
The above code will give me null in the 'author' field since my app uses password authentication. But i want to display the username which is stored in another collection of firebase, it is in the location of FirebaseFirestore.instance.collection("users").doc(user!.uid)
I'm really new to flutter and firebase, this is my first app i am making for my school project, any help or guidance will be appriciated.

Your question could've been framed better but based on my understanding, it seems new users do not have a displayName associated with the user object since you are using the email_id + password sign up option and you wish to retrieve the username which is stored in another collection of firestore under "users".
Future<String> _getUsername() async {
final user = FirebaseAuth.instance.currentUser;
final docSnap =
await FirebaseFirestore.instance.collection("users").doc(user!.uid).get();
return docSnap.get(
'userName'); //assuming the field within the document is titled ‘userName’
}
void _addMessage(String value) async {
final user = FirebaseAuth.instance.currentUser;
if (user != null) {
final userName = await _getUsername();
await FirebaseFirestore.instance.collection("interest_chat").add({
'author': userName,
'author_id': user.uid,
'timestamp': Timestamp.now().millisecondsSinceEpoch,
'value': value,
});
}
}

Related

Avoid user Login with Firebase on Creation [duplicate]

This question already has an answer here:
Flutter - remove auto login after registration in Firebase
(1 answer)
Closed 1 year ago.
I have an app where users are supposed to be created only by Admin User's the problem is that when a new user is created in Firebase the app sign's in with the new user information, so the original logged user (Admin User), has to logged out, and log back in to create a new user.
This is my function to create a new User:
void createUser(
String email,
String password,
String nombre,
String dui,
DateTime fechaNacimiento,
String telefono,
String nombreContacto,
String telefonoContacto,
DateTime fechaIngreso,
String radio,
File foto,
String acceso,
) async {
try {
final auth = FirebaseAuth.instance;
UserCredential authResult = await auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
//var uploadUid = authResult.user?.uid;
final ref = FirebaseStorage.instance
.ref()
.child('user_images')
.child(authResult.user!.uid + '.jpg');
await ref.putFile(foto);
final url = await ref.getDownloadURL();
await FirebaseFirestore.instance
.collection('users')
.doc(authResult.user!.uid)
.set({
'nombre': nombre,
'dui': dui,
'fechaNacimiento': fechaNacimiento,
'telefono': telefono,
'nombreContacto': nombreContacto,
'telefonoContact': telefonoContacto,
'fechaIngreso': fechaIngreso,
'radio': radio,
'foto': url,
'acceso': acceso,
'uid': authResult.user!.uid,
'correo': email,
'contrasena': password,
});
} catch (err) {
print(err);
}
}
Any Ideas on what to do to avoid the log in on user creation of the newly created user.
Kind Regards
The original admin user does not have to be logged out to create a new user. Simply do this.
FirebaseApp secondaryApp = await Firebase.initializeApp(
name: 'SecondaryApp',
options: Firebase.app().options,
);
try {
UserCredential credential = await FirebaseAuth.instanceFor(app: secondaryApp)
.createUserWithEmailAndPassword(
email: 'email',
password: 'password',
);
if (credential.user == null) throw 'An error occured. Please try again.';
await credential.user.sendEmailVerification();
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
return _showError('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
return _showError('An account already exists for this email.');
}
} catch (e) {
return _showError('An error occured. Please try again.');
}
...
// after creating the account, delete the secondary app as below:
await secondaryApp.delete();
The above code will not logout the admin user, the admin user can still continue with normal operations after creating the account.

firebase is not creating the user (user.uid = null)

I am trying to implemente facebook signin in flutter, however, firebase does not create a 'uid'. Doesn't the firebase create a uid automatically?
it returns:
The getter 'uid' was called on null.
Receiver: null
Tried calling: uid
below is the sign in method:
Future<UserCredential> signInWithFacebook(BuildContext context) async {
final LoginResult result = await FacebookAuth.instance.login();
if(result.status == LoginStatus.success) {
final OAuthCredential credential = FacebookAuthProvider.credential(result.accessToken.token);
return await FirebaseAuth.instance.signInWithCredential(credential)
.then((user) async {
final graphResponse = await http.get(Uri.parse(
'https://graph.facebook.com/v2.12/me?
fields=name,picture,email&access_token=${result
.accessToken.token}'));
final Map profile = jsonDecode(graphResponse.body);
if (profile != null){
authService.createUser(name: name, email: email, dob: dob, sex: sex);
}
return user;
});
}
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (context) => Profile()));
return null;
}
The sign in method returns a facebook alert dialog requesting the permission to share email, when press continue red screen with the error appears. why is the firestore not creating the user? Thanks! I am not familiar with the system and just learning.
create user method in authServices:
Future<bool> createUser(
{String name,
User user,
String email,
String password,
String phone,
String sex,
String dob}) async {
var res = await firebaseAuth.createUserWithEmailAndPassword(
email: '$email',
password: '$password',
);
if ((res.user != null)) {
await saveUserToFirestore(name, res.user, email, dob, phone, sex);
return true;
} else {
return false;
}
}
As far as I can understand your code you first login the user with Facebook and then again create a new user with createUserWithEmailAndPassword. If you use the same email for both the second one will fail and give you null.
To track the auth state for all providers use the onAuthStateChanged listener:
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
var uid = user.uid;
// ...
} else {
// User is signed out
// ...
}
});
More about it here.

Facebook login returns generic profile picture URL

Well I'm using the code from Firebase and the in the user object the photoURL which being returned is General facebook profile with no image
which is generic profile picture
Future signInWithFacebook() async {
try {
// Trigger the sign-in flow
final result = await FacebookAuth.instance.login();
// Create a credential from the access token
final FacebookAuthCredential facebookAuthCredential =
FacebookAuthProvider.credential(result.token);
// Once signed in, return the UserCredential
UserCredential res = await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
User user = res.user;
//create a new document for the user with the uid
await UserProfileDatabaseService(uid: user.uid).updateUserData(
user.displayName,
user.email,
user.emailVerified,
user.phoneNumber,
user.isAnonymous
, {'helper': true},
250
); return user;
} catch (e) {
print(e.toString());
return null;
}
}
you can use the following code to display the Facebook profile picture URL after a successful login:
await FacebookAuth.instance.login();
final user = await FacebookAuth.instance.getUserData();
Image.network(user["picture"]['data']['url']);
This code logs the user in via FacebookAuth, retrieves their user data, and displays their profile picture using the Image.network widget.

Displaying user data from Firebase Firestore in React Native within a Text tag

Background
Hey! I'm trying to build a header for the home page of my app. I have succesfully implemented email/password auth with Firebase and also persistent credentials. However, I am unable to fetch data from the firestore collection which stores my users.
Basically, what I need is to have my header display "Hello {userName}", but I have absolutely no clue on how to do that.
My Home Screen is a function component, not a class component, so as far as I know I can't go the "componentDidMount()" way.
Question
Which is the best way to fetch the current user's data and display a specific field of information, such as their first name?
How would I go about rendering that within a <Text> tag? Is it something like <Text> Hello {this.user.firstName}</Text> or am I absolutely wrong?
What I've tried
I know this has something to do with this line of code: const usersRef = firebase.firestore().collection('users') but I've no idea what to follow it up with. Also have tried with this method:
var user = firebase.auth().currentUser;
var firstName, email, photoUrl, uid, emailVerified;
if (user != null) {
firstName = user.firstName;
email = user.email;
photoUrl = user.photoURL;
emailVerified = user.emailVerified;
uid = user.uid;
}
But that doesn't seem to work. On the last example I'm calling firstName like this: <Text>Hello {firstName}</Text>
You are confusing auth with firestore. Firebase auth only provides credentials and the ability to login and does not enter any data into a database (firestore). What you want to do is when a user is registering you want to set a corresponding document in firestore with the users uid (identification) and all of the users custom data (First name, etc).
Here is an example:
const onRegister = async () => {
try {
const credential = await auth.createUserWithEmailAndPassword(
'email#email.com',
'password',
);
const {uid} = credential;
// your data here (dont forget to store the uid on the document)
const user = {
firstName: 'whatever',
lastName: 'whatever',
user_id: uid,
};
await firestore().collection('users').doc(uid).set(user);
} catch {
//do whatever
}
};
and then when you wanna get their data you can access their document and display it:
const [user, setUser] = useState();
const {uid} = auth().currentUser;
const getUser = async () => {
try {
const documentSnapshot = await firestore()
.collection('users')
.doc(uid)
.get();
const userData = documentSnapshot.data();
setUser(userData);
} catch {
//do whatever
}
};
// Get user on mount
useEffect(() => {
getUser();
}, []);
// return info if user is set
return (
<Text>{user && user?.firstName}</Text>
);

How to delete firebase account when user data is deleted on flutter?

is it possible to delete firebase account in authentication on flutter? if yes, how to do that? I have been search but not found the way.
Firestore.instance.collection("users").document(uid).delete().then((_){
// delete account on authentication after user data on database is deleted
});
Using flutter, if you want to delete firebase accounts together with the associated firestore user collection document, the following method works fine. (documents in user collection named by the firebase uid).
Database Class
class DatabaseService {
final String uid;
DatabaseService({this.uid});
final CollectionReference userCollection =
Firestore.instance.collection('users');
Future deleteuser() {
return userCollection.document(uid).delete();
}
}
Use Firebase version 0.15.0 or above otherwise, Firebase reauthenticateWithCredential() method throw an error like { noSuchMethod: was called on null }.
Authentication Class
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
Future deleteUser(String email, String password) async {
try {
FirebaseUser user = await _auth.currentUser();
AuthCredential credentials =
EmailAuthProvider.getCredential(email: email, password: password);
print(user);
AuthResult result = await user.reauthenticateWithCredential(credentials);
await DatabaseService(uid: result.user.uid).deleteuser(); // called from database class
await result.user.delete();
return true;
} catch (e) {
print(e.toString());
return null;
}
}
}
Then use the following code inside the clickable event of a flutter widget tree to achieve the goal;
onTap: () async {
await AuthService().deleteUser(email, password);
}
Code for deleting user:
FirebaseUser user = await FirebaseAuth.instance.currentUser();
user.delete();
To delete a user account, call delete() on the user object.
For more on this, see the reference documentation for FirebaseUser.delete().
User user = FirebaseAuth.instance.currentUser;
user.delete();
From this you can delete user

Resources