检查唯一用户名

时间:2017-02-12 13:59:07

标签: ios swift firebase firebase-realtime-database firebase-security

我想检查用户名是否已被使用。当前用户没有“username”子项时调用此函数:

func createUsername()
{
    let userID = FIRAuth.auth()?.currentUser?.uid
    FIRDatabase.database().reference().updateChildValues([
        "users/\(userID!)/username": username.text!,
        "usernames/\(username.text!)": userID!
        ], withCompletionBlock: { (error, reference) in
            if (error != nil) {
                print("disallowed")
                // Write was disallowed because username exists
            }
    })
}

结合这条规则:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid",
        "username": {
      ".read": true,
          ".write": "!data.exists() && newData.exists()",
          ".validate": "newData.isString()"
        }
      }
    },
    "usernames": {
      "$username": {
        ".read": true,
        ".write": "!data.exists() && newData.exists()",
        ".validate": "newData.isString() && newData.val() == root.child('users/' + auth.uid + '/username').val()"
      }
    }
  }
}

我得到了答案:https://groups.google.com/forum/#!topic/firebase-talk/dA1Lkykd-tk 我收到此错误消息:

  

[Firebase /数据库] [I-RDB03812] updateChildValues:at / failed:permission_denied

我不确定为什么这不起作用。我也试过这个答案:Firebase android : make username unique但这对我不起作用。规则有问题,但我不知道是什么。

更新,规则变化不大,仍然是同样的错误:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid",
        "username": {
      ".read": true,
          ".write": "!data.exists() && newData.exists()",
          ".validate": "newData.isString()"
        }
      }
    },
    "usernames": {
      "$username": {
        ".read": true,
        ".write": "!data.exists() && newData.exists()",
        ".validate": "newData.isString() && newData.val() == newData.parent().parent().child('users/' + auth.uid + '/username').val()"
      }
    }
  }
}

我也改变了父()的东西,但它也不会起作用。我换了4个父母,0个父母。同样的错误。

1 个答案:

答案 0 :(得分:1)

更新:问题来自此验证规则:

".validate": "newData.isString() && newData.val() == root.child('users/' + auth.uid + '/username').val()"

您正在将新数据与当前根进行比较。由于刚创建用户/users/$uid尚不存在。

您要做的是将新数据与 new 用户节点进行比较。要进入此节点,您应该在比较时从newData导航到 new 根目录:

".validate": "newData.isString() && 
  newData.val() == newData.parent().parent().child('users/' + auth.uid + '/username').val()"

我将在下面留下我之前的回复,因为它可能有助于学习如何解决此类问题。

我只是将您的规则粘贴到我的项目中,简化了一下并使用了您的代码而没有任何问题。我不确定你为什么遇到问题。

代码:

    FIRAuth.auth()?.signInAnonymously(completion: { (user, error) in
        let username = "puf"
        let userID = FIRAuth.auth()?.currentUser?.uid
        self.ref.child("42188459").updateChildValues([
            "users/\(userID!)/username": username,
            "usernames/\(username)": userID!
        ], withCompletionBlock: { (error, reference) in
            if (error != nil) {
                print("disallowed")
                // Write was disallowed because username exists
            }
        })
    })

规则摘要:

  "users": {
    "$uid": {
      ".write": "$uid === auth.uid",
      "username": {
        ".write": "!data.exists() && newData.exists()",
      }
    }
  },
  "usernames": {
    "$username": {
      ".write": "!data.exists() && newData.exists()",
    }
  }

结果JSON:

{
  "usernames" : {
    "puf" : "DBP4Pw3uiwQfUaDJw1XBR8oFBUK2"
  },
  "users" : {
    "DBP4Pw3uiwQfUaDJw1XBR8oFBUK2" : {
      "username" : "puf"
    }
  }
}