我的 Firebase 安全规则构建是否正确?

问题描述 投票:0回答:1

我一直在一遍又一遍地尝试重组我的规则,以便能够访问这些文档,但没有运气。

我有一个“网络”集合和一个“成员”子集合。在网络文档中有两个字段,loginRequired 和membershipRequired,它们确定访问网络文档及其子集合需要什么级别的身份验证。

我已在下面附上我的规则,并且已确认membershipRequired / loginRequired 字段均位于网络文档的顶层。

我在各个级别都遭到拒绝。我可能做错了什么?

match /networks/{networkID} {
      allow read: if (isAdmin()
       || !(planRequiresAuth())
       || (isLoggedIn()
            && (resource.data.membershipRequired
               ? (isPlanMember(database, networkID)
                   || isProviderPlanMember(database, networkID))
               : true)
               )
           )

      match /{document=**} {
        allow read: if (isAdmin()
          || !(get(/databases/$(database)/documents/networks/$(networkID))
               .data.loginRequired)
          || (isLoggedIn()
          && (get(/databases/$(database)/documents/networks/$(networkID))
               .data.membershipRequired
              ? (isPlanMember(database, networkID)
                || isProviderPlanMember(database, networkID))
              : true)
             )
            )
      }
}

// Utility Functions

    function isAdmin() {
      return hasRole('ADMIN')
    }
    function planRequiresAuth() {
      return (resource.data.loginRequired || resource.data.membershipRequired)
    }
    function isLoggedIn() {
      return request.auth != null
    }
    function isPlanMember(database, networkID) {
      // Check if the document ID is in the users memberships
      let userId = request.auth.uid;
      return exists(/databases/$(database)/documents/networks/$(networkID)/members/$(userId))
    }
    function isProviderPlanMember(database, networkID) {
      // Check if the document ID is in the users memberships
      let orgId = request.auth.token.meta.organizationId;
      return ((resource.data.membershipRequired == true) ? (exists(/databases/$(database)/documents/networks/$(networkID)/members/$(orgId))) : true)
    }
    function hasRole(role) {
      return role in request.auth.token.roles
    }

我尝试将其设置为允许所有读取,效果很好。 我尝试过允许所有子集合读取并且它也有效,但我有一种感觉这不是我想要的,因为子集合也需要门控。

编辑 返回权限被拒绝的查询。由于第一个查询被拒绝,第二个查询尚未被调用。我将两者都包含在内以获取完整的上下文。

collection('networks')
        .where('slug', '==', networkSlug)
        .get()
        .catch(err => {
          console.warn('  ** Error fetching network by slug') // eslint-disable-line no-console
          console.log(err) // eslint-disable-line no-console
          if (err?.code === 'permission-denied') {
            return { error: err, code: 'permission-denied' }
          }
          return { error: err, code: 'error-fetching' }
        })

collection('networks')
        .doc(networkId)
        .collection('landerInfo')
        .get()
        .catch(err => {
          console.log(err) // eslint-disable-line no-console
          return { error: err, code: 'error-fetching' }
        })

permission denied image

firebase google-cloud-firestore firebase-security
1个回答
0
投票

要对此进行调试,您应该转到 Firestore 控制台,然后在“规则游乐场”中运行查询,而不是在应用程序中运行查询。它将更准确地强调其被拒绝的逻辑。

无论如何,这里的问题是下面一行:

exists(/databases/$(database)/documents/networks/$(networkID)/members/$(userId))

Firestore 接受或拒绝查询的决定是在执行查询之前做出的(文档将其描述为“规则不是过滤器”)。在判断接受查询时,

networkId
还不知道(因为查询约束中没有指定,还没有得到查询结果),无法运行
exists
查询上面不知道
networkId

© www.soinside.com 2019 - 2024. All rights reserved.