【问题标题】:In Firebase Realtime Database Rules, how do you give write access to the users with a certain child value?在 Firebase 实时数据库规则中,您如何为具有特定子值的用户授予写入权限?
【发布时间】:2020-08-16 20:55:32
【问题描述】:
,"people" : {
  ".read": "auth != null",
  "$uid":  {
  },
  "e2" : {     
    ".read": "auth.uid != null",
    ".write": "$uid == auth.uid"  
  },
  "l1" : {     
    ".read": "auth.uid != null",
    ".write": "auth.uid != null"  
  }

所以 e2 是电子邮件的@。例如@gmail 或@aol 或@yahoo。对于 l1 孩子,我想制定写规则:写 if auth.uid != null && e2 与你正在写 l1 的人的 e2 具有相同的值。我能得到的最远的是这样的:

"data.parent().child(people).hasChildren(['auth.uid', 'l1'])"    

JSON

"people": {
    "02PdiNpmW3MMyJt3qPuRyTpHLaw2": {
        "e2": "aol.com",
        "l1": 4,
        "X": {
            "e2": "aol.com",
            "l1": 0,
            "P": {
                "e2": "gmail.com",
                "l1": 0,

基本上 l1 = like,所以一个用户以将计数加 1 的形式写入另一个用户的 l1。

应该成功的操作:

用户 X 想要喜欢 uid 为 02PdiNpmW3MMyJt3qPuRyTpHLaw2 的用户。用户 X 有一个 @aol.com 的 e2 子级。这与他想要喜欢的用户的e2孩子相同。用户 x 也是授权用户,因此他满足 2 个要求来写他想要喜欢的用户的 l1。

不应该成功的操作:

用户 P 想要喜欢 uid 为 02PdiNpmW3MMyJt3qPuRyTpHLaw2 的用户。用户 P 有一个 @gmail.com 的 e2 子级。这和他想要喜欢的用户的e2孩子不一样。用户P因此不满足写给他想点赞的用户的l1的要求

【问题讨论】:

  • 我很难解析这里的需求,e2l1 的名字肯定没有帮助。您可以编辑您的问题以包括:1)您尝试编写的数据库中的 JSON(作为文本,请不要截图)? 2)应该成功的写操作? 3) 一个应该失败的写操作。
  • @FrankvanPuffelen 感谢您的评论。 A 添加了您建议的内容。希望现在很清楚。
  • 不是用文字来描述操作,你能把它们写成代码吗?除此之外,至少有一个问题是auth.uid 不应该在data.parent().child(people).hasChildren([auth.uid, 'l1'])" 中使用引号
  • @FrankvanPuffelen 谢谢。我不知道如何在代码中编写它。这基本上就是我想要解决的问题。我得到的最接近的是 '"data.parent().child(people).hasChildren(['auth.uid', 'l1'])"',这并不接近。这样的规则可能吗?
  • 我仍然很难理解用例,因此无法为其建模规则。如果我正确理解 JSON sn-p,则意味着:1) 用户 X 喜欢用户 02PdiNpmW3MMyJt3qPuRyTpHLaw2。 2) 这是允许的,因为它们的e2 子节点的值是相同的。那是对的吗?如果是这样,l1 与这一切有什么关系?

标签: firebase firebase-realtime-database firebase-authentication firebase-security


【解决方案1】:

这是一个非常复杂的场景,所以我将逐步介绍它。您很有可能需要进行更改以使这些规则适用于您的完整用例,因此我希望每个步骤都可以让您自己调整它们。


第一步是对您的数据结构进行去混淆处理。我将改为使用此结构开始:

{
  "people" : {
    "user1" : {
      "domain" : "aol.com",
      "likeCount" : 2,
      "likers" : {
        "user2" : {
          "comain" : "aol.com"
        },
        "user3" : {
          "domain" : "aol.com"
        }
      }
    }
  }
}

所以user1 有两个赞,user2user3 都来自同一个域。

强烈建议在您的数据库中使用这样有意义的名称,但绝对是在您发布的有关它的问题中。如果人们不能轻易理解您的数据模型,那么他们提供帮助的机会就会迅速下降。


在上面的数据模型中,我们可以保证只有同域的用户才能点赞这个用户:

  "people": {
    "$uid": {
      "likers": {
        "$likerid": {
          ".write": "data.parent().parent().child('domain').val() == newData.child('domain').val()"
        }
      }
    }
  }

根据这些规则,我尝试了对people/user1/likers/user4 的两次写入操作。第一次操作成功:

{
  "domain": "aol.com"
}

第二次操作失败:

{
  "domain": "gmail.com"
}

我们或许还应该确保用户只能写自己喜欢的内容,而不能写给其他用户。我们可以这样做:

  "people": {
    "$uid": {
      "likers": {
        "$likerid": {
          ".write": "$likerid == auth.uid && 
            data.parent().parent().child('domain').val() == newData.child('domain').val()"
        }
      }
    }
  }

接下来,我们将添加一个规则,允许用户喜欢某人,前提是他们以前没有喜欢过某人。我们将在people/$uid 上执行此操作,因为我们需要很快查看likerslikesCount 下的数据。

第一步的规则是:

  "people": {
    "$uid": {
      ".write": "
        !data.child('likers').child(auth.uid).exists() && newData.child('likers').child(auth.uid).exists()
      ",
      "likers": {
        "$likerid": {
          ".write": "$likerid == auth.uid && 
            data.parent().parent().child('domain').val() == newData.child('domain').val()"
        }
      }
    }

因此,如果我们要添加尚不存在的类似内容,这些规则允许我们向用户写信。您可能需要在此处进行额外检查以允许更新其他子节点,但在这里我们将尽可能简单地处理(因为它已经非常复杂了)。


最后你要确保写入也必须增加likeCount,应该是这样的:

  "people": {
    "$uid": {
      ".write": "
        !data.child('likers').child(auth.uid).exists() && newData.child('likers').child(auth.uid).exists()
        && newData.child('likeCount').val() == data.child('likeCount').val() + 1
      ",
      "likers": {
        "$likerid": {
          ".write": "$likerid == auth.uid && 
            data.parent().parent().child('domain').val() == newData.child('domain').val()"
        }
      }
    }

所以新行现在检查likeCount 处的新数据是否比之前的值高一个。


我已经在自己的测试数据库中执行了上述每个步骤,并在操场上测试了阳性和阴性案例。因此,虽然可能存在一些问题,但每个步骤的基本方法都有效。

如前所述,这涉及相当多的内容,您很可能需要进行重大更改才能使其完全适用于您的所有用例。

【讨论】:

  • 只有在没有之前:如果规则还没有这样做,它将检查 newDatadata 的相关节点。每天:听起来也可以,例如通过扩展您的数据模型以在路径中包含日期。
  • 假设你在likers而不是$likerid做了第一次检查,你会少用一个.parent(),对吧?我已经有一个名为peopleWhoLike 的节点具有子表单[double]:childByAutoID: ikerid(///喜欢的用户的uid,当然在我的不称为likeid)。我试图让它在$peopleWhoLike 工作,但我怀疑它没有成功,因为它是双倍的。我正在编辑问题以添加该结构,但清楚地标记它在您的答案之后。
  • 最好将其放在评论中,否则对于仅阅读答案的人来说会造成混淆。这就是我尝试过的:所以第一个答案中的喜欢者有类似的东西叫做 peopleWhoLike,采用 json 格式:"peopleWhoLike" : { "Optional(\"-MDWpTyQjA6a1VzTWvEV\")" :"QqQpDheHC4cC9bs4KtreArFiS8g2", 那双是:childBYAutoID: uid
  • 我想知道答案中的第一条规则如何适用于 peopleWhoike、AKA likes 而不是 $likes。我试图使它与下面的喜欢一起工作,但没有成功:"peopleWhoLike" : {"$peopleWhoLike": { ".read": "auth.uid != null", ".write": "$peopleWhoLike == auth.uid" } }
  • 已删除提问者的评论:抱歉,我(提问者)在看到第一条评论已得到答复之前删除了它。我的评论,现在第一条评论的答案是:是否可以更改确保用户不能重新喜欢另一个用户的规则 - 因为第二天可能会重新喜欢。
猜你喜欢
  • 2017-01-25
  • 2016-03-13
  • 1970-01-01
  • 2017-01-28
  • 2019-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
相关资源
最近更新 更多