问题
After reading many articles about additional user data fields (in my case it's just unique username) in Firebase ecosystem, I approached the best (I hope) variant of saving and validating username - use the username as a node key under /users/
.
I'm validating username on the client side and inside database rules:
": "$user.matches(/^[0-9A-Z]{3,18}$/i)&& newData.hasChildren(['uid']) && !data.parent().hasChild($user)",
I'm facing problems when signing user up. In my SignUp method I save username to the database in successful promise resolve of createUserWithEmailAndPassword
method, here's a piece of code:
...
.createUserWithEmailAndPassword(payload.email, payload.password)
.then((user) => {
// saving additional user information
firebase
.database()
.ref(`users/${payload.username}`)
.set({
uid: user.uid,
})
.then(() => {
...
Client side validations is good, but obviously not enough. My application works ok, but if we disable client side validation of the username and try to submit invalid username - user will be created without username at all.
The only solution I see is to create username node first, if creation was successful - try to sign user up, if signing up won't throw any errors - continue program execution, otherwise in .catch
block just delete created node with the username. But it seems like a very dirty solution to me.
How can I solve this problem in elegant way? Thanks!
回答1:
The solution seems quite dirty and inelegant to me too. What I'd propose to do is to not go with the rules method to validate the username. Because, as you pointed out - you have no way to know when the validation fails.
Instead, I'd suggest you to write a database trigger function in your Cloud Functions implementation. This function should be triggered when the "username" node is populated. In this, you can validate the username to ensure that it meets whatever criteria that you've set. If, the validation is successful, your client app could indicate that to the user and proceed further.
If the validation is unsuccessful, you could ask the user to input another username. You could even display a progress bar or something similar in the client while the validation process takes places.
However, I'd like to add that this might just be one of the ways in which this can be solved and is not necessarily the best way. Although I can't think of a better way, I am entirely open to explore a different method if something else comes up!
回答2:
If you want to make sure you have required fields saved to the database, as well as no other 'not known' fields, you can use the .validate rule. Add this to your database.rules.json (or directly in Database rules in the console):
"users": {
"$uid": {
"email": { ".validate": true },
"displayName": { ".validate": true },
"$other": { ".validate": false },
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
Also, notice the recommended way to store a user in the Realtime Database, by using it's UID as the KEY. So your user path will look like:
/users/9gZepE9jODX1KZGZ2EEyoX1NyOX4
来源:https://stackoverflow.com/questions/46252458/how-to-create-user-in-firebase-only-if-database-fields-are-valid