Firebase android: mache den Benutzernamen einzigartig

Parse wird am Ende des Jahres heruntergefahren, also entschied ich mich, Firebase zu verwenden. Ich muss einen Registrierungsprozess mit 3 Feldern implementieren: E-Mail, Benutzername, Passwort ( E-Mail und Benutzername müssen für meine App eindeutig sein).

Da Firebase keine einfache Möglichkeit bietet, Benutzernamen wie Parse zu verwalten, entschied ich mich, nur die E-Mail / Passwort-Registrierung zu verwenden und einige zusätzliche Daten wie den Benutzernamen zu speichern. Hier ist meine Benutzerdatenstruktur:

app : { users: { "some-user-uid": { email: "test@test.com" username: "myname" } } } 

Aber ich möchte den Benutzernamen eindeutig machen und überprüfen, bevor ich ein Konto erstelle. Das sind meine Regeln:

 { "rules": { ".read": true, ".write": true, "users": { "$uid": { ".write": "auth !== null && auth.uid === $uid", ".read": "auth !== null && auth.provider === 'password'", "username": {".validate": "!root.child('users').child(newData.child('username').val()).exists()"} } } } } 

Vielen Dank für Ihre Hilfe

   

Ein Teil der Antwort besteht darin, einen Index von Nutzernamen zu speichern, gegen den Sie in Ihren Sicherheitsregeln überprüfen:

 app : { users: { "some-user-uid": { email: "test@test.com" username: "myname" } }, usernames: { "myname": "some-user-uid" } } 

Der usernames knüpft also einen Benutzernamen an eine Benutzer-ID. Es liest sich im Wesentlichen so, dass “Benutzername ‘myname’ im Besitz von ‘some-user-uid'” ist.

Mit dieser Datenstruktur können Ihre Sicherheitsregeln prüfen, ob für einen bestimmten Benutzernamen bereits ein Eintrag vorhanden ist:

 "users": { "$uid": { ".write": "auth !== null && auth.uid === $uid", ".read": "auth !== null && auth.provider === 'password'", "username": { ".validate": " !root.child('usernames').child(newData.val()).exists() || root.child('usernames').child(newData.val()).val() == $uid" } } } 

Dies bestätigt, dass der Benutzername noch nicht von jemandem beansprucht wurde ODER vom aktuellen Benutzer beansprucht wird.

Speichern Sie Benutzernamen wie von Frank vorgeschlagen, aber wenn Sie Benutzernamen speichern, verwenden Sie die function runTransaction in Firebase, um sicherzustellen, dass der Benutzername nicht vergeben wird. Diese function wird von Firebase als atomare Operation garantiert, so dass Sie sicher sein können, dass keine Kollision auftritt

 firebaseRef.child("usernames").child(username).runTransaction(new Transaction.Handler() { @Override public Transaction.Result doTransaction(MutableData mutableData) { if (mutableData.getValue() == null) { mutableData.setValue(authData.getUid()); return Transaction.success(mutableData); } return Transaction.abort(); } @Override public void onComplete(FirebaseError firebaseError, boolean commited, DataSnapshot dataSnapshot) { if (commited) { // username saved } else { // username exists } } }); 

Ich weiß noch nicht viel über Firebase-Sicherheit, aber ich habe das Problem möglicherweise mit Java getriggers. Ich habe es unten gepostet.

Meine Datenstruktur ist

 myapp { users: {  { username: "example.username" } } } public boolean isUsernameExists(final String enteredUsername) { final Boolean[] isExist = {false}; FBref.child("users").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) { String existingUsername = (String) userSnapshot.child("userName").getValue(); if (existingUsername.equals(enteredUsername)) { isExist[0] = true; } } } @Override public void onCancelled(FirebaseError firebaseError) { //some error thrown here } }); return isExist[0]; }