Firebase generating two different uid's for the same user? - javascript

Currently working on a React project that utilizes Firebase to store users. To make the user, I use createUserWithEmailAndPassword(). When the user is created in Firebase, it stores the user under an id that looks like -N4xrZ...
However, when I make a call to get the user's UID (through userCredential.user.uid), it returns a much longer one that looks like a typical UID generated by Firebase and that isn't the same as the user's parent id. Any ideas as to what this may be?

It stores the user under an id that looks like -N4xrZ...
That's the expected behavior since you're using push(). This function generates a unique ID each time is called.
When I make a call to get the user's UID (through userCredential.user.uid), it returns a much longer one that looks like a typical UID generated by Firebase and that isn't the same as the user's parent id.
The UID that comes from the authentication process, it's different than the one that is generated by push(). It's actually the same, each time you launch your app. So when you write data to the database, stop using push() and use the UID:
firebase.database().ref('users/' + userCredential.user.uid).set({
username: name,
email: email,
profile_picture : imageUrl
});

Related

Is there a Client.fetchUser() equivalent in Discord.js?

I was trying to find a way to get a User object from a user's ID alone. Client#fetchUser() seemed to be what I was looking for, referring to this
older question.
However that function is no longer in the Discord.js Client Object Documentation
And I can't seem to find a way of doing what fetchUser() is supposed to do. I need to create User Object from User IDs because I'm retrieving saved user data and need to be able to send messages to the users I'm retrieving from save data.
There are 2 ways to go about doing this:
Getting the user from the client.users.cache collection
const user = client.users.cache.get(UserID)
Fetching the user using the fetch() method in the UserManager of client.users
const user = client.users.fetch(UserID)
It seems they merged the functionality of UserManager#fetch()
into what I was looking for, in which it is described as
Obtains a user from Discord, or the user cache if it's already available.
PARAMETER TYPE OPTIONAL DEFAULT DESCRIPTION
id Snowflake
ID of the user
cache boolean true
Whether to cache the new user object if it isn't already
Returns: Promise<User>
So it'll either grab the user from the cache by ID, or retrieve it from Discord if it's not in the cache. I'm guessing they did this to make this functionality more efficient.

Getting a sub-collection by a specific field value in Firestore

How do I find a subcollection based on a field value? I am currently using this code but it doesnt work:
var user = db()
.collection('myCollection')
.doc()
.collection('private')
.where("nam", "==", this.state.passcode);
What I am trying to achieve is making a custom authentication, so giving a custom username and password to users (in this case just a passcode). So I decided to store those credentials in a separate sub-collection inside a document. How can a user authenticate by comparing the values of username and password with the ones of a sub-collection?
Another question, is sub-collection for credentials a good idea? Will it cost the same to me as if I would store those info in the document?
First of all, what you're doing right now is not secure at all. You should never store user credentials in a database, especially not one that's directly accessible to your web and mobile clients. To do this properly, you should be making use of Firebase Authentication to sign in users. (You tagged this question firebase-authentication, which refers to that product.) In fact, doing security properly is very difficult. Firebase Auth will make sure everything is done correctly.
Secondly, the query you have now will never yield any documents. That's because you're not passing anything to doc(), which means it will return a DocumentReference to a non-existent document with a random ID. If you meant to have some sort of unique identifier for each user, perhaps that's something you would want to pass to doc() so that each user's subcollection would be correctly identified.

How to handle multiple tabs using in firebase using realtime database

I am creating a multiplayer game website. I am using three features of firebase.
Firebase authentication
Firestore
Real time database
The data which is permanent is stored in firestore. Like profile image, username etc. The data in firestore is stored in collection users and the key is same as the authentication id which we get from user.uid
The second data is temporary data which contains the chat messages and current game situation and player turn etc. This data is stored in real time database.
There are two base objects in real time data base. One is rooms and other is users. When a user logs in to website the permanent data is taken from the firestore and placed with temporary data(because we might need to display the permanent data again and again). The function I am using to get permanent data and create combination with temp data is
//'uid' is the permanent id which is used in firestore and also in authentication.
export const addUser = async (uid: string) => {
//gets the permanent data from firestore
const data = await getUserData(uid);
//Set it to realtime database my adding one more temp prop
return await dbUsers.child(uid).set({...data, messages: []});
};
Till now everything is fine problem comes when I have to remove the user on disconnection. I used t
export const removeUser = async (uid: string) => {
return await dbUsers.child(uid).remove();
};
The above way doesn't work for multiple tabs. Consider if user had opened multiple tabs and he just closed one server then realtime database will consider it logged out.
Do I need to create realtime data on the basis of another id using push() method. Kindly guide me to correct path.
If I understand correctly you're trying to track the user's online status using Firebase's onDisconnect handlers. To do this:
You write a value for the user's UID when they connect.
You then delete that value using an onDisconnect handler.
This indeed will not work when the user opens the app in multiple locations (tabs, browsers, or devices). The reason is that a user can be online in multiple locations, and your code and data structure needs to cater for this.
The idiomatic approach is the one outlined in the sample presence app in the Firebase documentation, and works with a data structure like this:
"OnlineUsers": {
"uidOfUser1": {
"-LKeyOfConnection1": true,
"-LKeyOfConnection2": true
},
"uidOfUser2": {
"-LKeyOfConnection3": true,
"-LKeyOfConnection4": true
}
}
In this structure, if a user has two open connections (on different tabs, browsers, devices), they have two nodes under their UID, each with its own onDisconnect handler. When both connections are closed, with connection keys disappear, and thus their /OnlineUsers/$uid node also disappears automatically.
So to detect if a user is online in the above structure, you'd check if there is a node under /OnlineUsers with their UID.

Firebase Auth Built-in identity

I am building a web platform to connect learners with tutors using Firebase Auth and Firestore. I am storing the learners' user info in a Firestore collection, and the tutor's info in another. I am building a function that can detect if a client is a learner or a tutor upon login.
One solution I was thinking is to query in which collection the user is found using UID. Although, this is a potential solution. But it sounds like it requires a lot of transaction, and may have a long run time if collections get big. Is there something else I can do for that? I am wondering if I can use authentication to build an embedded identity to each user to differentiate between "Tutor" and "Learner"? So each time the user logs in, we know the identity immediately?
I know that in the decoded authentication token, there is info such as this:
{ iss: 'https://securetoken.google.com/xxxx',
aud: 'xxxx',
auth_time: 1569886929,
user_id: 'aB03',
sub: 'aB03',
iat: 1570582588,
exp: 1570586188,
email: 'aa#gmail.com',
email_verified: false,
firebase:
{ identities: { email: [Array] }, sign_in_provider: 'password' },
uid: 'aa3' }
Can I leverage one of these to build what I want?
Really appreciate your time and help.
Since you mention "collection", I assume you're looking to use Firestore. In that case: the size of the collection has no effect on the query performance. No matter if there are 1,000 user documents in the collection, 1,000,000 or even 1,000,000,000, the time it takes to query for a single user document will always be the same.
Aside from that you can also store the user's type in the ID token (which is what you've shown in your question). This is known as a "custom claim", since you're adding a custom property for your app to the information. You'll want to do this from a trusted environment (your development machine, a server you control, or Cloud Functions), as I'd assume users should not be able to change their own role. See the documentation on controlling access with custom claims for more information on this.

Meteor: Adding fields to Third Party User creation

I am using the user-accounts package to manage the Account System in my app.
I have also integrated Google, Github, Twitter and other 3rd party Services.
The package works fine, but now that I need a specific page for every user, and for SEO terms, I need the url to be like this:
https://domain.com/user/username
I also have the accounts-password package. And I have added a username field, and it works fine.
But if thirdparty services are used, the popup closes and the page is redirected with the user successfully created. I read about calling Accounts.onUserCreate,
and this is my code:
Accounts.onCreateUser(function(options, user) {
var email = options.profile.email;
var ist = email.indexOf("#");
var uname = email.slice(0,ist);
user.username = uname;
if(options.profile){
user.profile = options.profile;
}
return user;
});
But it gives an error : Cannot read indexOf of undefined.
How can this be achieved?
There either can be a page, to enter the username, for every new user, or this way, the email should be sliced for username creation. (Second method is preferred.)
The error message is telling you your variable email has not been set.
When using third-party login services with Meteor, the user information is not stored within the profile of the user document. Rather, you should look for the email within the services data of that user document. For example, for Facebook, you should find this within services.facebook.email.
You may also want to consider using the user argument to find this information as the documentation states: "The user argument is created on the server and contains a proposed user object with all the automatically generated fields".

Categories

Resources