【问题标题】:Firestore rules: How do I check the contents of a map on all documents in a collection?Firestore 规则:如何检查集合中所有文档的地图内容?
【发布时间】:2020-12-12 23:44:56
【问题描述】:

我正在尝试完成以下功能:

  • 用户可以加入比赛
    • 如果他们还没有比赛
    • 如果他们还没有参加比赛,他们正在尝试加入
    • 如果他们不在匹配集合中的任何其他匹配中

我在最后一个问题上苦苦挣扎。我试过这个:

!exists(/databases/$(database)/documents/matches/$(uid)/players/$(request.auth.uid)) // if the user is not already in another match

...但它似乎不起作用。

这是我的规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /userAuthData/{uid}/{documents=**} {
      allow read: if false
      allow write: if false
    }
    match /userData/{uid}/{documents=**} {
      allow read: if request.auth != null && request.auth.uid == uid
      allow write: if false
    }

    function allowCreateMatch(uid) {
      return request.auth != null 
        && exists(/databases/$(database)/documents/userData/$(request.auth.uid)) // if the user exists
        && !exists(/databases/$(database)/documents/matches/$(request.auth.uid)) // if the user does not have their own match already
        && !exists(/databases/$(database)/documents/matches/$(uid)/players/$(request.auth.uid)) // if the user is not already in another match
        && request.resource.data.maxPlayers == 2 // if the match is set to have 2 players (1v1 is the default for now)
        && request.resource.data.state == 1 // if the match is set to a state of WAITING_FOR_PLAYERS
    }

    function allowJoinMatch(uid) {
      return request.auth != null 
        && exists(/databases/$(database)/documents/userData/$(request.auth.uid)) // if the user exists
        && !exists(/databases/$(database)/documents/matches/$(request.auth.uid)) // if the user does not have their own match already
        && !exists(/databases/$(database)/documents/matches/$(uid)/players/$(request.auth.uid)) // if the user is not already in another match
        && !(request.auth.uid in resource.data.players) // if the user is not already in the match
        && resource.data.players.keys().toSet().size() < resource.data.maxPlayers // if there is room left based on the max number of players
        && resource.data.state == 1 // if the match is in a state of WAITING_FOR_PLAYERS
        && resource.data.maxPlayers == request.resource.data.maxPlayers // if there max players value is the same
        && request.resource.data.players.keys().toSet().size() + 1 == resource.data.maxPlayers
          ? request.resource.data.state == 2 // the match is should be set to a state of READY_TO_START
          : request.resource.data.state == 1 // the match is should be set to a state of WAITING_FOR_PLAYERS
    }

    function allowDeletion() {
      return request.auth.uid == resource.id
        && resource.data.state == 1
    }

    match /matches/{uid}/{documents=**} {
      allow read: if true
      allow create: if allowCreateMatch(uid)
      allow update: if allowJoinMatch(uid)
      allow delete: if allowDeletion()
    }
  }
}

【问题讨论】:

    标签: javascript firebase google-cloud-firestore firebase-security


    【解决方案1】:

    除了简单的单文档get() 之外,安全规则无法执行查询。不允许查询未知数量的文档,因为它们不会按照安全规则要求的方式扩展。

    如果您无法通过获取单个文档来表达您的规则,那么您将需要以某种方式更改您的数据以使其成为可能,或者将您的写入路由到可以执行您需要的查询的某个后端.

    【讨论】:

    • 您对如何重组我的数据有什么建议吗?我可以轻松做到,但不知道如何解决我的问题。如果存在上述限制,您将如何实现一个模型成为另一个模型的成员的概念?
    • 我不知道根据您在此处描述的内容。这完全取决于你。如果您尝试过某事,但它没有按您期望的方式工作,请发布一个新问题。对于这个问题,最重要的是您的规则不起作用,因为它实际上无法像我描述的那样进行查询。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多