What Firebase rule will prevent duplicates in a collection based on other fields?

一个人想着一个人 提交于 2019-12-27 12:03:31

问题


I'm creating an application which lets users create items and then allow other users to subscribe to those items. I'm struggling to craft a rule that will prevent users from subscribing more than once to an item.

Here is an example of my data structure (anonymized, hence the "OMITTED" values):

{
    "OMITTED" : {
        "name" : "Second",
        "body" : "this is another",
        "userName" : "Some User",
        "userId" : "OMITTED",
        "created" : 1385602708464,
        "subscribers" : {
            "OMITTED" : {
                "userName" : "Some User",
                "userId" : "OMITTED"
            }
        }
    }
}

Here are my Firebase rules at present:

{
  "rules": {
    ".read": true,
    ".write": "auth != null",
    "items": {
      "$item": {
        ".write": "!data.exists()",
        ".validate": "newData.hasChildren(['name', 'body', 'userId', 'userName']) && newData.child('userId').val() == auth.id",
        "subscribers": {
          "$sub": {
            ".validate": "newData.hasChildren(['userId', 'userName']) && newData.child('userId').val() != data.child('userId').val()"
          }
        }
      }
    }
  }
}

How can I prevent users from subscribing more than once? What is the rule I need to prevent duplicate users within the subscribers list based on userId?


回答1:


Since security rules can't iterate a list of records to find the one containing a certain bit of data, the trick here is to store the records by an ID which allows for easy access. There is a great article on denormalization which offers some good insights into this practice.

In this case, if your use case allows, you may simply want to switch your data structure so that records are stored by the user's id, rather than storing the ID as a value in the record, like so:

/users/user_id/items/item_id/subscribers/user_id/

In fact, as you'll see in denormalization, you may even benefit from splitting things out even farther, depending on the exact size of your data and how you'll be reading it later:

/users/user_id
/items/user_id/item_id
/subscribers/item_id/user_id

In either of these formats, you can now prevent duplicates and lock down security rather nicely with something like this:

{
   "users": {
      "$user_id": { ".write": "auth.id === $user_id" }
   },
   "subscribers": {
      "$subscriber_id": { ".write": "auth.id === $subscriber_id" }
   }
}


来源:https://stackoverflow.com/questions/20260476/what-firebase-rule-will-prevent-duplicates-in-a-collection-based-on-other-fields

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!