使用查询的get()和exist()规则获取缺少或权限不足的信息

时间:2019-03-26 10:41:35

标签: android firebase web google-cloud-firestore firebase-security-rules

我们尝试列出“事件”集合中的所有文档。 (/event/{eventId}) 在每个事件的文档中,都存在一个属性“ users”(数组),其中包含所有用户的ID。 我们还有另一个集合“角色”,每个事件的每个用户的角色。 (/role/{eventId}/userRole/{userId}

我们有权参加一个活动

db.collection('event').doc(eventId).get()

但是当我们尝试(通过android和网络)进行类似

的查询时
db.collection('event').where("users", "array-contains", user.uid).get()

我们得到了FirebaseError: Missing or insufficient permissions.

活动规则:

    match /event/{eventId} {
      allow read:
        if isAuth() && 
        inEvent(eventId, request.auth.uid);
      allow create: 
        if isAuth() &&
        checkEventName() &&
        isOwner(database) &&
        request.resource.data.users == [];
      allow update:
        if isAuth() &&
        resource.data.ownerId == request.auth.uid &&
        checkEventName() &&
        isOwner(database) &&
        request.resource.data.mediaCount == resource.data.mediaCount &&
        request.resource.data.users == resource.data.users;
      allow delete:
        if false;
    }

角色规则:

    match /role/{roleId} {
      allow read: 
        if isAuth();
      allow write:
        if false;

      match /userRole/{userRoleId} {
        allow read:
          if isAuth() &&
          userRoleId == request.auth.uid;
        allow create:
          if isAuth() &&
          userRoleId == request.auth.uid && 
          exists(/databases/$(database)/documents/event/$(roleId)) &&
          request.resource.data.actual is number &&
          request.resource.data.actual >= 0 &&
          request.resource.data.actual <= 10 &&
          request.resource.data.previous is number &&
          request.resource.data.actual == request.resource.data.previous;
        allow update: 
          if isAuth() &&
          userRoleId == request.auth.uid &&
          request.resource.data.actual == 0 &&
          resource.data.actual != 0;
        allow delete: 
          if false;
      }
    }

角色ID与事件ID相匹配。

在事件的读取规则中,我们具有inEvent(eventId,request.auth.uid)。 当我们写

function inEvent(eventID, userID) {
      return true;
}

查询有效,但如果我们尝试类似的操作

return exists(/databases/$(database)/documents/role/$(eventID)/userRole/$(userID));

return get(/databases/$(database)/documents/role/$(eventID)/userRole/$(userID)).data.actual >= 10;

我们总是会出现权限错误

我们已经检查了所有数据和规则,但是我们不明白为什么可以得到单个事件而不是列表。我们做错了什么?我们可以使用get()和exist()获得列表权限吗?

1 个答案:

答案 0 :(得分:0)

首次添加侦听器时,将强制执行Firebase的安全规则。届时,服务器必须能够验证读取操作将永远仅返回您有权接收的文档。在当前规则中,这将要求服务器读取每个events文档,然后检查每个文档的用户角色。这是不可扩展的操作,因此服务器不允许它并且拒绝读取。

这通常意味着您要保护的信息应该出现在您试图允许访问的文档中(或该文档下的子集合),或者位于当前用户的固定位置。对于您的情况,我能想到的最好的办法是在读取事件的情况下使用ACL,尽管即使这样,我仍然不确定是否可以对其建模,以便服务器可以进行静态评估。

另请参阅: