33

FirebaseSimpleLoginユーザーの作成と認証の処理に使用しています。

メソッドを介して単純なログインで新しいユーザーを作成しようとすると$createUser()、メールアドレスが既に使用されている場合、firebase はユーザーを作成しません。ただし、$set()作成したユーザーを作成した後、作成したユーザーをfirebaseに保存するためにも使用してuser.uidおり、キーとして使用しています。データベースに書き込もうとすると、単純なログインにはメールとパスワードのみが必要なため、ユーザー名が一意でなくても、firebase はレコードを保存します。では、ユーザー オブジェクトのキーとして使用されていないユーザー名が一意であることを検証するにはどうすればよいでしょうか。

次のような新しいユーザーを作成しています。

$scope.createUser = function() {
  $scope.auth.$createUser('trinker@gmail.com', 'password').then(function(user, err) {
    if (!err) {
      ref.child('users/' + user.uid).set({
        email: user.email,
        username: user.username
      });
      console.log("success!");
    }else{
      console.log(err.message);
    }
  });
}

そして、私のユーザーオブジェクトは次のようになります:

{
  "users" : {
    "simplelogin:28" : {
      "email" : "trinker@gmail.com",
      "username" : "jtrinker"
    },
    "simplelogin:30" : {
      "email" : "test@gmail.com",
      "username" : "jtrinker"
    }
  }
}

}

各ユーザーのキーとして uid を使用する必要がありますが、ユーザー名は一意である必要があります。

あるオブジェクト内のプロパティが別のオブジェクト内のプロパティに固有でない場合、firebase がレコードを保存しないようにするにはどうすればよいですか?

4

2 に答える 2

35

まず第一に、ユーザーがすでに を持っている場合username、それはユニークであり、これがなくならない場合は、単純なログイン の使用をあきらめることをお勧めしますuid。ここですでに発見したように、これは 2 つの間を行ったり来たりしようとする問題を引き起こすだけです。firebase-passport-loginなどのツールを使用して独自のトークンの作成を調査し、 .username

しかし、それはあなたの質問ではなかったので、私たちがここにいる間に解決しましょう.

ユーザー名を一意にするには、ユーザー名のインデックスを保存します。

/users/$userid/username/$username
/usernames/$username/$userid

それらが一意であることを確認するには、usernames/ パスのユーザー ID に次のようにセキュリティ ルールを追加します。

".write": "newData.val() === auth.uid && !data.exists()"

users/ レコードのユーザー名に次を追加して、それらが一致するように強制します。

"users": {
   "$userid": {
      "username": {
         ".validate": "root.child('usernames/'+newData.val()).val() === $userid"
      }
   }
}

これにより、ID が一意になります。読み取り権限には注意してください。プライベートなメールやユーザー名を誰かに調べてほしくないので、それらを完全に避けたいと思うかもしれません. これらの保存をサポートするために私が示したようなものが理想的です。

ここでの考え方は、ユーザー名と電子メールを割り当てようとして失敗した場合、それらは既に存在し、別のユーザーに属しているということです。それ以外の場合は、それらをユーザー レコードに挿入すると、ユーザーは uid と電子メールでインデックス付けされます。

SOプロトコルに準拠するために、その要点からのコードを次に示します。これは、リンクから読む方が適切です。

var fb = new Firebase(URL);

function escapeEmail(email) {
   return email.replace('.', ',');
}

function claimEmail(userId, email, next) {
   fb.child('email_lookup').child(escapeEmail(email)).set(userId, function(err) {
      if( err ) { throw new Error('email already taken'); }
      next();
   });
}

function claimUsername(userId, username, next) {
   fb.child('username_lookup').child(username).set(userId, function(err) {
      if( err ) { throw new Error('username already taken'); }
      next();
   });   
}

function createUser(userId, data) {
   claimEmail(userId, data.email, claimUsername.bind(null, userId, data.username, function() {
      fb.child('users').child(userId).set(data);
   );   
}

そしてルール:

{
  "rules": {
     "users": {
        "$user": {
           "username": {
               ".validate": "root.child('username_lookup/'+newData.val()).val() === auth.uid"
           },
           "email": {
               ".validate": "root.child('email_lookup').child(newData.val().replace('.', ',')).val() === auth.uid"
           }
        }
     },

     "email_lookup": {
        "$email": {
           // not readable, cannot get a list of emails!
           // can only write if this email is not already in the db
           ".write": "!data.exists()",
           // can only write my own uid into this index
           ".validate": "newData.val() === auth.uid"
        }
     },
     "username_lookup": {
        "$username": {
           // not readable, cannot get a list of usernames!
           // can only write if this username is not already in the db
           ".write": "!data.exists()",

           // can only write my own uid into this index
           ".validate": "newData.val() === auth.uid"
        }
     },
  }
}
于 2014-08-15T14:50:39.323 に答える