2017-02-14 54 views
0

在我使用Firebase创建的iOS应用中,每个用户都有一个唯一的用户名,他们在用电子邮件和密码注册后创建。为什么此Firebase数据库安全规则使用&&和||不工作

所以,如果有[email protected]的电子邮件用户已经签署了,然后必须创建一个唯一的用户名这是不是在用户名数据库的数据库的一个片段将如下:

"usernames" : { 
     "test" : "r6KPesUr1qORfIJke07SloZHeNW2", 
     "test1" : "jSMSkY9rHtdNkXoLrsFmCAXdY9n2", 
     "test7" : "jnFhJbgCjZeJFx0hspObqoskQej2", 
     "test8" : "HtnULzU0lnZKYva2M2Wepl6N8wE3" 
    }, 

    "users" : { 
     "HtnULzU0lnZKYva2M2Wepl6N8wE3" : { 
      "email" : "[email protected]", 
      "username" : "test8" 
     }, 
     "boX6rtJ98haWVxNoXfSq21maCVU2" : { 
      "email" : "[email protected]" 
     }, 
     "jSMSkY9rHtdNkXoLrsFmCAXdY9n2" : { 
      "email" : "[email protected]", 
      "username" : "test1" 
     }, 
     "jnFhJbgCjZeJFx0hspObqoskQej2" : { 
      "email" : "[email protected]", 
      "username" : "test7" 
     }, 
     "r6KPesUr1qORfIJke07SloZHeNW2" : { 
      "email" : "[email protected]", 
      "username" : "test" 
     } 
    } 

我有以下安全规则来确保用户完成注册时用户名是唯一的。

// USERNAMES 
    "usernames": { 
     ".read": "auth.uid != null", 
     ".write": "auth.uid != null", 
     "$username": { 
      ".validate": "(!root.child('usernames').hasChild($username.toLowerCase()) && newData.val() == auth.uid && 
          root.child('users').hasChild(auth.uid)) && 

          (root.child('users/'+auth.uid+'/username').val().toLowerCase() == $username || 
          !root.child('users/'+auth.uid+'/username').exists())"     
     }         
    } 

因为我想有这三个语句作为必备品

(!root.child('usernames').hasChild($username.toLowerCase()) && 
    newData.val() == auth.uid && 
    root.child('users').hasChild(auth.uid)) 

的验证规则,并与这两个语句其中之一必须是真实的

"(root.child('users/'+auth.uid+'/username').val().toLowerCase() == $username || 
    (!root.child('users/'+auth.uid+'/username').exists()" 

所以如果用户想要注册test5作为用户名与下面的JSON那么它不会与我目前的安全规则,由于第一部分OR语句。

 "users": { 
     "boX6rtJ98haWVxNoXfSq21maCVU2": { 
       "username": "test5" 
      } 
    } 

我在做什么错?

+0

解析规则非常困难。你可以编辑你的问题,包括将被这个验证规则拒绝的最小代码,但你想允许吗? –

+0

@FrankvanPuffelen肯定的事情。我已经添加了数据库的外观以及后来未能写入的json为用户创建一个唯一的用户名,邮件地址为[email protected] – Edward

+0

OK。我试图弄清楚你的用例。但是从这样复杂的规则中理解很困难,所以我分离出了​​一个(两个)特定的用例,并专注于此。 –

回答

1

好像你想两件事情对用户要求用户名:

  1. 一个节点/users/$uid/username下写有自己的用户名
  2. 一个节点/usernames/$username下写他们的UID

您现在编写的JSON片段仅包含#1。它不包含关于在/usernames下编写用户名的内容。因此,该规则将拒绝它,因为您正在验证用户名必须存在并被该用户声明。

你可能想验证#1和#2发生在同一时间,这将是一个多位置更新,如:

"users/boX6rtJ98haWVxNoXfSq21maCVU2/username": "test5", 
"usernames/test5": "boX6rtJ98haWVxNoXfSq21maCVU2" 

你的规则是:

"usernames": { 
    "$username": { 
    ".validate": "!data.exists() && 
     newData.exists() && 
     newData.parent().parent().child('users').child(auth.uid).child('username').val() === $username" 
    }         
} 
"users": { 
    "$uid": { 
    "username": { 
     ".validate": "!data.exists() && 
     newData.exists() && 
     newData.parent().parent().parent().child('usernames').child(newData.val()).val() === $uid" 
    } 
    } 
} 

我删除了关于小写字母的一点,因为在代码中修复它并且只存储小写用户名更容易。

+0

我认为你需要从newData()中删除“用户”和“用户名”中的最终规则的括号 – Edward

+0

我不确定我明白你的意思。尽管建议编辑。 –

相关问题