Why is firebase creating a random identifier between parent and child? - javascript

I'm playing around with a firebase web app and having some difficulty diagnosing where something is coming from.
I am trying to simply push some data to my project under the heading of the uid created when authentication takes place. The authentication works fine and it is returning the uid correctly however, when values are passed it seems to be adding a second layer before the actual values.
function registerAccount() {
var firebase = app_firebase;
var firebaseRef = app_firebase.database(); //database reference
var user = firebase.auth().currentUser;
uid = user.uid;
var ref = firebaseRef.ref('User').child(uid); //referencing node
var userName = document.getElementById("txtUsernameInput").value;
if (user) {
// User is signed in.
var data = { //data being added
Username: userName,
}
window.location = 'myHome.aspx';
} else {
// No user is signed in.
console.log("Cannot get UID");
}
ref.push(data);
}
I am expecting the data entry to show with the child of user to be the uid taken from the authentication (this is working) then have the passed values immediately in the uid without the seemingly auto generated child between the uid and the values.
Image shows the unwanted field being generated
[See here][1]

André Kool's suggestion in a comment:
Change ref.push(data); to ref.set(data);
worked.

Related

How to add new members in Group using Firebase

I am developing the app which has grouping function.
Now I have the problem about adding new member in group.
Like Slack, in group creating onboarding flow user can decide group name and add members which don't use the app yet.
As adding members function, I want to use inviting mail link using firebase dynamic links.
Data structure is below
User
- id
- name
- email
Group
- id
- groupName
- members[]
Group's members array has user id.
But when someone creates new group, it is possible that new users don't register the app yet.
So they don't have user id property in the app.
How do I fix this problem?
When someone creates new group, should I develop sign up functions new user using Firebase auth? This means then new member has automatically user id, and adding those to members property.
Or should group member array have mail address instead of user id.
Please tell me. I'm happy with Swift or JavaScript you will teach me.
Thank you.
UPDATE
After reading your comment I would propose another approach.
When the Group creator user adds users to a group, if a user does not already exists you could, from the front-end, call a Callable Cloud Function (CF) that creates a temporary Firestore document in a specific collection. The ID of this document will be the (future) userId.
Then, still in this same Cloud Function, you send an email to the email address (you need to generate yourself the email, for example with the email extension) with a link containing the userId as query string value.
Example of code for this first CF:
exports.provisionNewAccount = functions
.https.onCall(async (data, context) => {
try {
// You can check that the caller is authenticated
// if (context.auth.uid) {execute the rest of the code} else {throw an error}
// New user email
const userEmail = data.email;
// Generate the new user docID
const fakeDocRef = admin.firestore().collection('_').doc();
const requestId = fakeDocRef.id;
// Create the doc in a specific collection
await admin.firestore().collection('usersCreationRequests').doc(requestId).set({ email: userEmail, treated: false });
// Generate the link to include in the email
const linkURL = 'https://your.app/register.html?requestId=' + requestId
// Send the email by creating a doc in the Extension collection
await db
.collection("emails")
.add({
to: userEmail,
message: {
subject: "....",
html: `Click to create your account` // adapt the html to add some text
},
});
return {result: 'OK'}
} catch (error) {
console.log(JSON.stringify(error));
throw new functions.https.HttpsError('internal', JSON.stringify(error));
}
});
You call it as explained here, by passing the future user's email.
When the email recipient clicks on the link, you open a specific page of your web app that shows a set of fields for the future user to enter his password, display name etc. Then on clicking on a sign-in button in this page you call a Callable Cloud Function passing it the Firestore document ID plus the field values (you get the document ID from the query string).
As shown below, this Cloud Function creates the user in the Authentication service (using the Admin SDK) and flag the Firestore document as treated. Upon getting back the Cloud Function result in the web app you authenticate the user (you have his email and password, since he/she entered it in the form).
exports.createNewAccount = functions
.https.onCall(async (data, context) => {
try {
const userEmail = data.email;
const userId = data.userId;
const userPassword = data.password;
const userDisplayName = data.displayName;
// Fetch the user doc created in the first CF
const snapshot = await admin.firestore().collection('usersCreationRequests').doc(userId).get();
const treated = snapshot.get('treated');
const email = snapshot.get('email');
if (!treated && userEmail === email) {
const createUserPayload = {
email,
emailVerified: false,
password: userPassword,
displayName: userDisplayName
};
const userRecord = await admin.auth().createUser(createUserPayload);
return { result: 'OK' }
} else {
return { result: 'User already created' }
}
} catch (error) {
console.log(JSON.stringify(error));
throw new functions.https.HttpsError('internal', JSON.stringify(error));
}
});
I’m actually using this exact approach for a B2B collaborative web app in which users can invite new users by email.
INITIAL ANSWER
(Totally different from the update)
So they don't have user id property in the app… How do I fix this
problem? When someone creates new group, should I develop sign up
functions new user using Firebase auth?
You can use the Anonymous Authentication mode, it exactly corresponds to your needs:
You can use Firebase Authentication to create and use temporary
anonymous accounts to authenticate with Firebase. These temporary
anonymous accounts can be used to allow users who haven't yet signed
up to your app to work with data protected by security rules. If an
anonymous user decides to sign up to your app, you can link their
sign-in credentials to the anonymous account so that they can continue
to work with their protected data in future sessions.
When signing-in with Anonymous Authentication a userId (uid) will be created and later you will be able to convert an anonymous account to a permanent account
I always use userId to achive this kind of feature, you can use anonymous authentication to get userId after user click invite link, Then if needed unlock more feature with furter authentication(add more provider).
If you only using mail address without authentication, It's hard to write rules for prevent user access unwanted data, Like anyone knew your email are able to access your account.

#ionic change the data key in firebase

I'm trying to update/add data on firebase. I used the Facebook login and I want to use the UserID as a key for the new data aded.
(check pict below)
The userID that I want to use it:
I want to replace that key with the userID:
fblogin(){
this.facebook.login(['email'])
.then(res=> {
const fc = firebase.auth.FacebookAuthProvider.credential(res.authResponse.accessToken);
firebase.auth().signInWithCredential(fc)
.then(fs => {
this.facebook.api('me?fields=id,name,email,first_name,picture.width(720).height(720).as(picture_large)', []).then(profile => {
this.newuser = {name: profile['first_name'] ,email: profile['email'],picture: profile['picture_large']['data']['url'],phone:''}
this.navCtrl.push(HomePage);
console.log(fs.uid);
this.db.list('/users/'+ fs.uid).update(this.newuser);
});
I got this error in compilation:
supplied parameters do not matchany signature of call target
In this line: this.db.list('/users/'+ fs.uid).update(this.newuser);
Any help?
The FB error looks correct. You cant update on the uid as the user has been saved with a unique FB id
You do not show the code that created the users record in the database, but what i think you want to do is set and object when you first save the users record. However this could be an issue because the user could be saved before the return of the uid. I cant tell with your code snippet. Regardless, I will write the code that i think will work if the users/ record is created at the time that of registration.
The service
async signupUser(email: string, password: string) {
try {
const result = await this.afA.auth.createUserWithEmailAndPassword(email, password);
return result;
} catch (err) {
console.log('error', err);
}
}
So this initially creates a user without facebook, The key here is that the users FB uid was created and is held in the returned result
The component
this.authData.signupUser(email,password).then(userData => {
console.log(userData) // <- this is result
}
Then we create a record in FB with the uid returned
this.db.object(`users/${userData.uid}/`).set(data);
.set(data) is whatever data you want to save in the users/uid namespace.
So basically you need to create that user table with its uid namespace when the user first registers. Then you can update the user with the uid returned from the facebook fs.uid
With your current code you could find the user based on the email ( because the email should be unique to all users) and then update ...
with lodash is it just
let foundUser = find(this.db.list('users'),{ 'email' : fs.email }
// and then update based on the object key
this.db.list('/users/'+ Object.keys(foundUser)).update(this.newuser);
i fixed the problem by using:
this.db.object('/users/'+ fs.uid).update(this.newuser);
instead of :
this.db.list('/users/'+ fs.uid).update(this.newuser);
And it works correctly !
Thanks all for help.

cant synchronize correctly with realtime database of firebase

As part of my studies I need to develop web-app (javasript language) Where we work with firebase realtime database.
currently inside the database,I have a tree of users objects that representing all the users who registered to the system. And what I'm trying to do is a simple user login function.
After the user entered his username and his password, I created an array to enter the entire user tree from a database. The problem is that when im calling the function from the Firebase it's not enough to ended.. and what happens is that the array remains empty and you can not verify that the user is registered on the system.
now I have used a temporary solution that Im using setTimeout function,I understand that this is wrong programming, and also i do not want the user to wait 2 seconds every time he wants to login to the system.
Can someone please help me? how to do it right without the setTimeout function?
I want that the function of the Firebase ends so only then start with the Authentication process.
Here is the code I wrote so far,
var correntUser;
var userlist = [];
var usersRef = database.ref('users');
// Query that inserts all users keys and names to an array.
usersRef.orderByChild("username").on("child_added", function(snapshot)
{
userlist.push({userKey:snapshot.key,username:snapshot.val().username,password:snapshot.val().password});
});
setTimeout(function()
{
//check if user exist in userlist.
for(var i=0; i<userlist.length;i++)
if (userlist[i].username == usernameArg && userlist[i].password == passwordArg)
correntUser = userlist[i].userKey;
if(correntUser == undefined)
{
//check if undefined
alert("wrong username or password");
document.getElementById("username").value = "";
document.getElementById("password").value = "";
return;
}
mainPage.addHeader();
},2000);
thank you all.
There is no need to manually check all users and see if there is a match with the attempted login credentials when Firebase provides built-in authentication. Password-based accounts require email addresses, although you can combine the username with any domain name to satisfy that requirement as suggested here.
You did not explain what your database structure looks like under the users path, but one way to handle that is to incorporate the user's unique id that gets returned as part of the createUserWithEmailAndPassword password:
function createAccount(email, password) {
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(function(userData) {
// account created successfully
usersRef.child(userData.uid).set({
email: email,
creation_date: new Date(),
...
})
}
.catch(function(error) {
...
})
}
Then for login attempts:
function login(email, password) {
firebase.auth().signInWithEmailAndPassword(email, password)
.then(function(userData) {
// login successful
mainPage.addHeader();
})
.catch(function(error) {
alert("wrong username or password");
document.getElementById("username").value = "";
document.getElementById("password").value = "";
})
}

Firebase set new unique ID

I'm new to firebase and practicing creating a ToDo application. So far this is my code:
Code:
var getUserRef = firebase.database().ref('users');
getUserRef.on('child_added', function(data) {
var name = data.child("name").val();
var email = data.child("email").val();
$('#loadData').append(`<tr><td>${name}</td><td>${email}</td><td>Edit Remove</td></tr>`);
});
function addUser() {
var database = firebase.database();
var name = $('#name').val();
var email = $('#email').val();
var newID = 4; // How can this be incremented?
database.ref('users/' + newID).set({
name: name,
email: email
});
}
Data Structure:
As you can see, everytime I create a new user, I am manually changing the newID variable.
My problem is I don't want to change it everytime I insert a new user. I want it to aumotically increment or generate a random unique ID.
Is there a way to do this in google firebase?
What you have here is a list of items. If you have such a list, it is common to use Firebase's push() method to add new items to it. This will generate a chronological key that is guaranteed to be unique across all clients, even in cases where some clients may have temporarily lost their network connection while they're adding data. These push IDs are not as readable as your array indices, but they are the recommended way of adding items to a list.
That said; you're not dealing with any list here, it is a list of users. If you're using Firebase Authentication to manage the user accounts and handle authentication, the users come with a build in id called uid. In such a case it makes more sense to store the items under their natural key, so under their uid in this case.
Yes there is.
Here is a code from firebase docs of an example of Push().
var messageListRef = firebase.database().ref('message_list');
var newMessageRef = messageListRef.push();
newMessageRef.set({
'user_id': 'ada',
'text': 'Example of text.'
});
You can find all this information about other methods here :
https://firebase.google.com/docs/reference/js/firebase.database.Reference

Dynamically creating member pages

I am new to website creation and I am using login/membership features. How would I dynamically create a new, permanent web page (profile page) for a member once they sign up?
//where I would use the code
//Javascript
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
//Navigate to the User's page, which does not yet exist
var url = "http://example.com/" + user.uid;
window.location = url;
} else {
// No user is signed in.
}
});
The answer is in the docs.
https://firebase.google.com/docs/auth/web/manage-users#get_a_users_profile
I suggest having a read of some FireBase documentation, you'll likely need to find out about how FireBase routing works (assuming you're using it as a server)
However, for your requirements (i.e. a user profile page), you can just grab the data and display it at a general profile URL.
var user = firebase.auth().currentUser;
var name, email, photoUrl, uid;
if (user != null) {
name = user.displayName;
email = user.email;
photoUrl = user.photoURL;
uid = user.uid; // The user's ID, unique to the Firebase project. Do NOT use
// this value to authenticate with your backend server, if
// you have one. Use User.getToken() instead.
}

Categories

Resources