How to handle different-case usernames in Firebase? - firebase

I'm having an issue with Firebase DB involving case sensitive keys. For example: I create a "Username" key for every new user that registers. I'm validating this "Username" value through regex and also checking if the value entered already exists in the database (checking username availability). My issue is that I just realized Firebase assumes different sentence case of the same value is a different value.
For example:
"Username": john and
"Username": John are seen as two different/unique usernames
I was thinking taking the user's desired username input string and making it all caps (or all lowercase), creating uniformity in the database, but then it would kill the ability of having a mixed-case username. Is there a way to bypass this?

I had the same issue using firebase. The solution was create a new property with lowercase for "searchable" fields on my system. Also I remove the accents from words on this property.

Related

manually validate/accept users flutter firebase

so im building an app which has 2 users(staff and student) and the staff must accept/verify users manually. thereby when the student registers/signs up this would show up as a request on the staff side then after the staff accepts or rejects the request which allows the studentto enter the app. i've already coded the sign-in sign up pages which looks very similar to this using firestore authentication.
the only solution i could think of is adding the user sign up info as a request and saving it under a firestore collection("registration requests") i though about how the password field might be an issue but i found that people used the flutter_string_encryption package to save the password as a .doc field. then when the staff accepts the request the method/ function .createUserWithEmailAndPassword(email: email, password: password) would be called but i don't know if this is the "correct" way of achieving this.honestly i have no idea how to tackle this problem. is there is any resource that tackle the same issue or any other way this could be archived?
You could implement a system whereby any student can create an account using .createUserWithEmailAndPassword() but the account has an associated flag/boolean which prevents them from viewing content until it is true.
E.g
Student creates account using .createUserWithEmailAndPassword().
Upon creating new user, create a FireStore document containing a boolean set to false if the account is unverified.
Allow teachers to alter the FireStore record for students and change the boolean value to true upon verification.
Dynamically display content to users based on wether the boolean in their FireStore record is set to true or false.
If this sounds feasible, I can provide more detail on the specific code if you're not familiar with the packages.

How to avoid entering a repeated data in firebase documents?

My database is quite simple. A collection and inside, there are documents with user information, including their username.
(I am doing this in flutter and firestore).
What I want is to prevent two users from having the same username.
I am doing this to insert the data.
FirebaseFirestore.instance.collection('users').add({
'username': 'username',
'desc': 'some bio',
'fieldone': 'aaa',
'fieldtwo': 'bbb',
// other user info
});
And to consult the data of a user (by their username).
FirebaseFirestore.instance.collection('users').where('username', isEqualTo: 'username').get();
At the moment I insert the data, what can I do to verify that said username is already in the database?
So if the username already exists, return an error and don't let insert it. And if it doesn't exist yet, it can be inserted.
What query can help me for this?
I am new to firebase. :(. Thanks.
What query can help me for this?
This can't be accomplished by a single query. You will have to take the steps you outlined already in your question. You will have to first query for documents with that username, then only insert a new one if there were none found.
However, you should be aware that there is a race condition here. If two people are trying at the same time to add the same username, it's possible that they both end up adding a document.
The only way to ensure uniqueness in Firestore is using the document ID. You might want to consider using the ID of the document to store the username (or some version of it, like a hash) so that a race condition can never occur, and that you only have one document with that username.
See also:
Firestore unique index or unique constraint?
Cloud Firestore: Enforcing Unique User Names
Unique field in Firestore database + Flutter
firebase rule for unique property in firestore
As you can see, your issue has already been thoroughly discussed on Stack Overflow.

Firebase: How to handle users with same displayNames when they sign up with Google Provider?

I have an app where people can sign up for user accounts. They can use their Google account or sign up using email/password. I am storing the user's displayName in Firestore so I can reference it throughout the app as their username.
However, there is a problem:
Let's say "John Doe" signs up for a user account on my app and he uses his Google account named johndoe#gmail.com. His Google account's display name is also "John Doe". However, a few days later, another with the same name "John Doe" signs up for a user account, and although his Google account email may be different (let's say, johndoe2#gmail.com), his display name is still the same. Now, I have 2 users in my app with the same display name "John Doe". This causes an issue when I am trying to create user name routes such as: https://myapp.com/JohnDoe and handling user profile lookups.
What is the recommended way to allow users to use their Google accounts if there are other users that may have the same display names? The catch is I don't want to store UIDs in the URL as I want it to be clean with just the displayName.
The catch is I don't want to store UIDs in the URL as I want it to be clean with just the displayName.
It might be clean, as long as the number of characters within the displayName is reasonable. In your example, "John Doe", contains only 8 characters, including the whitespace character between the names, which is fine. But I've seen so many examples of names that are larger than 28, the number of characters that exist in a UID. Since the displayName property is set within the Google account and it can be changed only by the user, you're having three solutions left.
The first one would be to create your own mechanism for setting specific user names into your application. These user names can be set especially by the users. It can be the same as the names in the Google account or not. However, when someone chooses "JohnDoe" and a second user wants to set the same user name, it won't be possible, since a "JohnDoe" is already present. So before setting a new user name, you should always check if that one is already present. You can do that because it's something that you control. When using Firestore, this can be simply done by using:
db.collection("users").whereEqualTo("userName", "JohnDoe");
Or when using the Realtime Database:
db.child("users").orderByChild("userName").equalTo("JohnDoe");
Now, the first "John Doe" will have a profile that looks like this:
https://myapp.com/JohnDoe
While the second one might have something like this:
https://myapp.com/John_Doe
See the underscore? This kind of mechanism is very widely used. Facebook, Instagram, Twitter, eBay, Reddit, and many more do that:
https://www.facebook.com/JohnDoe/
https://www.instagram.com/JohnDoe/
https://twitter.com/JohnDoe/
https://www.ebay.com/usr/JohnDoe/
https://www.reddit.com/user/JohnDoe/
The second one would be to ignore the user names and use only the UIDs that come from the authentication process. Case in which, your URL will look like this:
https://myapp.com/TwentyEightCharactersLong
That's not unusual, since other big apps use it:
https://www.imdb.com/user/$userId/
The third one would be to create a combination between the UID and the user name. The best example would be Stackoverflow:
https://stackoverflow.com/users/$userId/$userName/
// ^ ^
Or LinkedIn:
https://www.linkedin.com/in/$userName-$userId/
// ^ ^
Doesn't matter which solution will you apply, you'll always have unique URLs. But it's up to you to choose which one of these solutions seems more clear to you.
It's quite common to see URLs suffixed with some random number or combination of alphanumeric characters like john-doe-1 and so on. That being said you would have to implement logic for this yourself maybe using Firebase Auth Triggers for Cloud Functions which will run whenever a new user is created and you can add an URL for their name.
You could also add some random string like /users/john-doe-qwerty and maybe add a paid feature that allows user to set their own URLs (if applicable for your application) i.e. vanity URLs.
I recently had this issue too, after playing around with 2 separate Google Play accounts, I found that the user.UserId is static and unique, and while the user.DisplayName can be changed, display names are unique.
Therefore, you should be safe storing data under UserId and then grabbing their current display name on login. Alternatively, to match your wants, you can save the data under the display name but you might want to track their user identification code in case they change their display name (if you wish to accommodate that)

Where is password reset link stored in wordpress database

If you use Wordpress's built in password reset service it will go something like this:
Click forgot password
Enter your email or username
Receive a link in your email inbox
Click the link
Fill out form
That link you click, will look something like this:
http://yourdomain/wp-login.php?action=rp&key=vqwwSPzf6OK6bUv42XPk&login=natelough
If you try to change the &login to another name, it will reject you.
So, somewhere that 'key' is being stored in some way, and compared.
Where is it stored in the database?
I did an export of the database and searched the db for that string. It returned no results.
So what gives?
That key is generated by hashing a random string. You can see how this key is generated in the WordPress developer reference.
To answer your specific question, when a key is generated it is stored in the users table in the user_activation_key column. Only the most recently generated key is stored (invalidating previous reset keys). The key is also removed from the database once it has been used.
If you are looking to send these keys programmatically, you can generate them when you need them using get_password_reset_key(). That function accepts a WP_User object as its argument.
Depending on what you are trying to accomplish, there may be a more "best practices" way to do it than accessing that function directly.
The password is stored as a hash of the login name and password. You will find it in the users table under user_pass as an incomprehensible string. If the login name is changed, the entered password hashed with the login name will not match the string found in the database where the password was hashed with the original login name.

Membership switch from ID to email

Currently I have a site (asp.net 3.5) that uses a unique ID for the login. I am going to need to switch it to use emails if possible. I am going to be creating all new accounts so I can wipe the membership table clean and import all the user info.
We are switching from generic logins for departments to individual accounts.
Any links or pointers in the right direction would be greatly appreciated.
So here is what you should do.
If you are creating a entire user base just wipe of the current ones and tell users to create the new user with a email, as long as you validate that on the entry form you are going to be good.
Now if you already have a user base, then is a little more complicated.
First verify that every current user has a valid distinct email, then you have to change 2 columns on the aspnet_Users table, the columns are UserName, and LoweredUserName.
That should be simple if the first step is true, just do a loop for every aspnetMembership row, get the column Email and set as UserName, then get the column LoweredEmail a set as LoweredUserName.
Ta daaaaaa!
Now you have it all migrated to the new model, for new entries, make sure that the entry form validates the UserName to be an email, for that you can use RegEx.

Resources