简体   繁体   中英

Firebase permission denied when checking unique username

I want to check if the username already is in use. This function gets called when the current user does not have a child of "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
            }
    })
}

In combination with this rules:

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

I got the answer from: https://groups.google.com/forum/#!topic/firebase-talk/dA1Lkykd-tk I get this error message:

[Firebase/Database][I-RDB03812] updateChildValues: at / failed: permission_denied

I am not sure why this wont work. I also tried this answer: Firebase android : make username unique But this did not work for me. There is something wrong with the rules but I dont know what.

Update, little change in rules, still same error:

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

I also changed the parent() things, but it wouldn't work aswell. I changed to 4 parents, and 0 parents. Same error.

Update: The problem comes from this validation rule:

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

You're comparing the new data against the current root. Since the user has just been created /users/$uid won't yet exist.

What you want to do is compare the new data against the new users node. To get to this node, you should navigate from newData up to the new root when comparing:

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

I'll leave my previous response below, since it may prove useful in learning how to troubleshoot a problem like this.

I just pasted your rules into a project of mine, simplified them a bit and used your code without problems. I'm not sure why you're having a problem.

The code:

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

The rules snippet:

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

The resulting JSON:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM