web-dev-qa-db-ja.com

Firebase Android:ユーザー名を一意にする

Parseは年末にシャットダウンするため、Firebaseの使用を開始することにしました。メール、ユーザー名、パスワードの3つのフィールドで登録プロセスを実装する必要があります(Email&usernameはアプリで一意である必要があります)。

FirebaseはParseのようなユーザー名を管理する簡単な方法を提供していないため、メール/パスワード登録のみを使用し、usernameなどの追加データを保存することにしました。ユーザーデータ構造は次のとおりです。

app : {
    users: {
       "some-user-uid": {
            email: "[email protected]"
            username: "myname"
       }
    }
}

しかし、私がしたいことは、ユーザー名を一意にし、アカウントを作成する前にそれを確認することです。これらは私のルールです:

{
    "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()"}
            }
        }
   }
}

手伝ってくれてありがとうございます

31
FloGz

答えの一部は、セキュリティルールでチェックするユーザー名のインデックスを保存することです。

app : {
    users: {
       "some-user-uid": {
            email: "[email protected]"
            username: "myname"
       }
    },
    usernames: {
        "myname": "some-user-uid"
    }
}

したがって、usernamesノードはユーザー名をuidにマップします。基本的には、「ユーザー名「myname」は「some-user-uid」が所有しています」と読みます。

このデータ構造により、セキュリティルールは、指定されたユーザー名のエントリが既に存在するかどうかを確認できます。

"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"
    }
  }
}

これは、ユーザー名がまだ誰にも要求されていないことを検証しますOR現在のユーザーに要求されています。

48

Frankの提案に従ってユーザー名を保存しますが、ユーザー名を保存するときは、FirebaseのrunTransaction関数を使用して、ユーザー名が使用されないようにします。この機能はFirebaseによってアトミック操作であることが保証されているため、衝突が発生しないことを安心できます。

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
        }
    }
});
5
Viven