Firebase - Saving data - firebase

I have a question regarding the firebase.
I'm developing an app where there are three screens: the 'registration screen' where the user will create an account with email and password. The 'building profile screen', where the user will answer some questions to be implemented in his profile, (such as "What's your name?"). And finally the 'profile screen', where the user information will be displayed, such as the user name.
On the 'registration screen' I'm having no problem, the user fills in the email input and password input, and by clicking "create account", calling .createUserWithEmailAndPassword, the user account is created and it is taken to the 'building profile screen'. The question I'm having is in the 'building profile screen'. My question is: How can I save the user name and other data?
I read some articles on the subject but I had difficulty understanding. Can any of you guys help me with this?

You're going to want to create a node or multiple nodes in firebase for each user to hold their user-specific information. The database structure could be uniform like so:
users: {
uid_a: {
username: 'uid_as_username',
email: 'uid_as_email',
name: 'uid_as_name',
other_attribute: 'uid_as_other_attribute_value'
[,...]
},
uid_b: {
username: 'uid_bs_username',
email: 'uid_bs_email',
name: 'uid_bs_name',
other_attribute: 'uid_bs_other_attribute_value'
[,...]
}
[,...]
}
or split up like so:
usernames: {
uid_a: 'uid_as_username',
uid_b: 'uid_bs_username'
[,...]
},
emails: {
uid_a: 'uid_as_email',
uid_b: 'uid_bs_email'
[,...]
},
names: {
uid_a: 'uid_as_name',
uid_b: 'uid_bs_name'
[,...]
},
other_attribute: {
uid_a: 'uid_as_other_attribute_value',
uid_b: 'uid_bs_other_attribute_value'
[,...]
}
Which you choose is a design choice, but thats the idea.

Just complementing #Vincent answer, by default you can store the user name, email and photoUrl within firebase auth (read get user profile: https://firebase.google.com/docs/auth/web/manage-users).
If you need to store more info, like postal address, phonenumbers, and so on, you can create a node in your database like users and store all the data you need. You can even use the same UID created for auth as the ID of your database. This way it would be easier for you to get user infos in the future.
When you just create the user with email and password, you can return the user and add it to your database with a script like this
firebase.database.ref(`Users/${user.uid}`).set({
name: this.state.name,
email: this.state.email,
});
Consider the code above just as an example.
Prefer to use .set() instead of .push(). If you use .push() firebase will create a random id which you will not be able to change. Using .set() you can determine the value of your node.
Hope it helps.

This is taken from the official documentation that might give you clue how to update and fetch data from database.
Set up Firebase Realtime Database for Android
Connect your app to Firebase
Install the Firebase SDK. In the Firebase console, add your app to
your Firebase project. Add the Realtime Database to your app
Add the dependency for Firebase Realtime Database to your app-level
build.gradle file:
compile 'com.google.firebase:firebase-database:11.2.2'
Configure Firebase Database Rules
The Realtime Database provides a declarative rules language that
allows you to define how your data should be structured, how it should
be indexed, and when your data can be read from and written to. By
default, read and write access to your database is restricted so only
authenticated users can read or write data. To get started without
setting up Authentication, you can configure your rules for public
access. This does make your database open to anyone, even people not
using your app, so be sure to restrict your database again when you
set up authentication.
Write to your database
Retrieve an instance of your database using getInstance() and
reference the location you want to write to.
// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");
myRef.setValue("Hello, World!");
You can save a range of data types to the database this way, including
Java objects. When you save an object the responses from any getters
will be saved as children of this location.
Read from your database
To make your app data update in realtime, you should add a
ValueEventListener to the reference you just created.
The onDataChange() method in this class is triggered once when the
listener is attached and again every time the data changes, including
the children.
// Read from the database
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
String value = dataSnapshot.getValue(String.class);
Log.d(TAG, "Value is: " + value);
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});

Related

firebase auth token from Graphcool

can I generate a custom auth token, for use with a third party, with a resolver in graph.cool? something like this??
type FirebaseTokenPayload {
token: String!
}
extend type Query {
FirebaseToken(userIdentifier: String!): FirebaseTokenPayload
}
const fb = require('myNodeFirebaseAuthLib')
module.exports = event => fb.generateTokenWithPayload({ id: event.data.userId })
Authentication required - restrict who can read data in fields: Permission query:
query ($user_id: ID!, $node_firebaseIdentifier: String) {
SomeUserExists(filter: {
id: $user_id ,
firebaseIdentifier: $node_firebaseIdentifier
})
}
--
I think this question boils down two parts
"is it possible to install node modules in the graph.cool instance -- or for that sort of thing do we need to use a webhook" -- if it must be a webhook, what is the flow of identity verification and how do I pass the payload parameters ?
"can we add permissions queries and authentication to resolvers?"
notes, addendums:
according to this alligator.io blog post, it seems that using the Graphcool framework, you can install node modules! So, I wouldn't need to use a webhook. -- However, that is with an ejected app. I lose auth0 authentication that way -- the template does not produce a createUser and singinUser that works with the same auth0 data that the integration offers.
I forgot to post the answer to this - I had to eject graphcool, I could not use any node_modules I thought to try in my custom functions.

Should firebase auth onCreate trigger have more data?

I'm using functions.auth.user().onCreate() as part of a firestore project, and trying to set up some default data when a new user registers. For the front end, I'm using firebase-ui, with Google and Email/Password providers enabled.
When I sign in with an email and password, the UI widget prompts to enter a name and set a password. I was expecting to see the name as part of the user parameter in the onCreate() function call, but I'm getting practically nothing:
user: { email: 'xxx#yyyy.co.uk',
emailVerified: false,
displayName: null,
photoURL: null,
phoneNumber: null,
disabled: false,
providerData: [],
customClaims: {},
passwordSalt: null,
passwordHash: null,
tokensValidAfterTime: null,
metadata:
UserRecordMetadata {
creationTime: '2018-11-20T15:06:01Z',
lastSignInTime: '2018-11-20T15:06:01Z' },
uid: 'QDJ5OJTwbvNo2QNDVQV9VsxC2pz2',
toJSON: [Function] }
Not even getting the provider info so I can tell which 'kind' of user registered. It's almost like this function is triggered before the user record has been populated (except the email address does get through). Also, registrations via the Google provider come with a fully-populated user record, so I guess this is a problem with Email/Password specifically.
Is this a bug, or am I missing something? I didn't see anything else useful in the context parameter either.
The fact that displayName is not populated in the Cloud Functions onCreate trigger for email+password is expected. The function is triggered from the first API call (createUserWithEmailAndPassword()), while the display name is set with a second API call (updateProfile).
The usual workaround would be to create a Cloud Function to update the user profile, as shown here: Firebase Auth+Functions | create user with displayName
I also highly recommend filing a feature request to be able to have a Cloud Function triggered on profile changes.

How to check Item exists in Firebase Database? - react-native-firebase

Currently, I am using https://github.com/invertase/react-native-firebase for my project. I have a custom database for users and I want to check if the user exists or not by email.
Here is a screenshot of the database:
Here's a generic firebase method but you may need to reconfigure the method to suit your data structure. Please refer to the official docs if you wish to know more.
firebase.database()
.ref(`/users`)
.orderByChild("email")
.equalTo(email)
.once("value")
.then(snapshot => {
if (snapshot.val()) {
// data exist, do something else
}
})
You can also query the registration status with hasChild method. Refer to your root path and query with .once and check the result returned.
export function checkUserExist(email) {
return(dispatch) => {
firebase.database().ref(`/ExistingUser/`)
.once('value', snapshot => {
if(snapshot.hasChild(email)) {
dispatch({
type: FIREBASE_USER_EXISTED
});
} else {
dispatch({
type: FIREBASE_USER_NOT_EXISTED,
});
}
});
}
}
Another preferred method would be using the fetchProvidersForEmail method provided by Firebase. It takes an email and returns a promise that resolves with the list of providers linked to that email if it is already registered, refer here.
Is there a good reason to store users credential in your database? In my daily practice, I would use the createUserWithEmailAndPassword provided by Firebase for security purposes, refer here. Just make sure rules are defined properly to prevent unauthorized access.

Firebase verify multiple email addresses for the same user

I'm using Firebase web SDK 4.0.0 and want to enable my users to verify multiple email addresses for the same account. For context, my objective is to receive email from dave#home.com and dave#work.com and know that it's definitely coming from Dave (uid 123456789).
I've looked up the docs about linking accounts but I'm assuming this approach isn't going to work as I need multiple emails.
I thought about storing the emails in the db and linking them to the user but that doesn't hook into the Firebase verification process (which I want to use).
Any ideas of how to approach this would be very helpful.
If you want a user have multiple emails registered in his account. You have to do the linking in the firebase database. Below is how to implement the structure in the database.
{
"userAuth": {
"userId001": {
"userRNGId": "abc123",
"userEmail": "example01#gmail.com"
},
"userId002": {
"userRNGId": "abc123",
"userEmail": "example02#gmail.com"
}
},
"userList": {
"abc123": {
"userName": "James",
"occupation": "Programmer",
"userAccounts": {
"userId001": {
"userAuth": "userId001"
},
"userId002": {
"userAuth": "userId002"
}
}
}
}
}
With this structure you can still use firebase authentication to verify their email address.
userId001 and userId002 is the RNG created from firebase authentication.
Inside userRNGId(E.g abc123) you should create random user ID so that all the emails will be linked to that id.
I hope it helps.

How do you delete user accounts in Meteor?

The only way I have found to delete user accounts in meteor (other than emptying the database with mrt reset), is by actually logging into that specific user account, and deleting the account from the console, using:
Meteor.users.remove('the user id');
But like I said, I need to be logged in as that specific user, and have not been able to find a solution which enables me to delete any user from the db. I'm sure it has something to do with permissions or roles, but I am not sure how to proceed / what is the best solution / how to set an administrative role for a particular user, so that I can delete different user accounts.
You could do
meteor mongo
or
meteor mongo myapp.meteor.com for a deployed app
Then
db.users.remove({_id:<user id>});
I wouldn't recommend it but if you want to delete any user without being logged in from meteor you would need to modify the allow rules. But deleting a user is a very unlikely event hence the above might be the best way to do it.
Anyway if you do want, modify the Meteor.users.allow({remove:function() { return true }); property. See http://docs.meteor.com/#allow. You could add in some custom logic there so it'll only let you do so if you're the admin
I was having trouble doing this on nitrous.io because I couldn't open both Meteor and Mongo. I put:
Meteor.users.remove(' the _id of the user ');
in the isServer section to remove the user.
If anyone is still looking for an answer to this question, I have outlined my solution below.
When I create a new user, I add a field called role in my user document. If I want a user to be able to remove other users from the Meteor.users collection, I give him a role of administrator. If not, I give him a role of member. So, my user document looks something like this -
{
"_id" : ...,
"createdAt" : ...,
"services" : {...},
"username" : "test",
"profile" : {
"name" : "Test Name",
"role" : "administrator"
}
}
On the client, I have a list of users (added using a #each template tag) with a remove button next to each user. A user has to login to see this list. I defined an event handler for the remove button -
'click #remove-user-btn': function () {
Meteor.users.remove({ _id: this._id }, function (error, result) {
if (error) {
console.log("Error removing user: ", error);
} else {
console.log("Number of users removed: " + result);
}
})
}
However, Meteor.users does not allow remove operations from the client by default. So, you have to edit the Meteor.users.allow callback in the server as shown below to allow the users to be removed from the client side. But we need to make sure that only a user with an administrator role is allowed this privilege.
Meteor.users.allow({
remove: function (userId, doc) {
var currentUser, userRole;
currentUser = Meteor.users.findOne({ _id: userId }, { fields: { 'profile.role': 1 } });
userRole = currentUser.profile && currentUser.profile.role;
if (userRole === "administrator" && userId !== doc._id) {
console.log("Access granted. You are an administrator and you are not trying to delete your own document.");
return true;
} else {
console.log("Access denied. You are not an administrator or you are trying to delete your own document.");
return false;
}
},
fetch: []
});
This is the general idea. You can build upon this to suit your needs.
Here are the steps to delete user from mongo through console:
step 1: open new console
step 2: change diretory to your app such as (cd myapp)
step 3 : enter command meteor mongo
step 4: make sure there exists a table called users, db.users.find({});
step 5: find the userid of the user you wish to delete and type :
db.users.remove({_id:"nRXJCC9wTx5x6wSP2"}); // id should be within quotes

Resources