0

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

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

我正在为最后一个而苦苦挣扎。我试过这个:

!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()
    }
  }
}
4

1 回答 1

1

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

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

于 2020-12-13T00:41:08.150 回答