Firestore:如何使用用户作为字段名称对对象类型设置安全性

时间:2018-06-26 03:03:13

标签: swift google-cloud-firestore firebase-security-rules

据我了解,Firestore不允许在类型为array的字段中进行查询,这很可惜。因此,如果希望能够查询数组的内容,则必须将一个字段设置为对象类型,然后将这些字段设置为地图,这称为嵌套地图。我想要一张地图,其中的钥匙是另一个用户的ID。因此,数据库结构为:

database
  users
    {userId}
        friends
           userId1: true
           userId2: true

“ userId1”和“ userId2”字段名称会根据列出为朋友的人的userId有所不同。

问题是,如何编写我的安全规则,以便我可以找到我的文档(通过我的{userId})和其他用户的文档,而我的{userId}是另一个用户的“朋友”对象中的字段用户的文档?

我想应该是这样的。

  match /users/{userId} {
      allow read, update, delete: if resource.data.userId == request.auth.uid;
      allow read: if resource.data.friends.{userId} == true;
    }   

但是这当然不起作用,因为您似乎无法使用变量{userId}来命名要对其进行测试的字段。因此,如果无法做到这一点,那么如何搜索文档并将我的{userId}以某种方式存储在其他人的文档中?


编辑


好吧,我想我已经确定了规则(见下文)。但是,当尝试测试这些规则时,我似乎无法编写Swift调用来基于该friends对象检索数据。我的Swift电话是:

db.collection("users").whereField(FieldPath(["friends.\(userId)"]), isEqualTo: true)

所以,我的问题是:

  1. 以下规则正确吗?
  2. 如何进行Swift调用以在对象类型的字段名称中查找具有特定userId的人员?

    服务cloud.firestore {     匹配/ databases / {database} / documents {         匹配/ users / {documentId} {             允许读写:if isOwner();
                允许读取:如果getFriend(request.auth.uid)== true;

            function isOwner() {
                return request.auth.uid == resource.auth.uid;
            }
    
            function getFriend(userId) {
                return getUserData().friends[userId]
            }
    
            function getUserData() {
                return get(/databases/$(database)/documents/rooms/{documentId}).data
            }
        } 
    }
    

    }

1 个答案:

答案 0 :(得分:1)

我仍然没有解决访问对象中字段的问题,但是请注意,我的安全规则通常无效。例如,您不能有多行具有相同的规则类型,也不能有多行带有“ allow:read”。您必须使用&&和||。例如,如果要检查两件事,则基本规则的正确定义是:

// Database rules
service cloud.firestore {
    // Any Cloud Firestore database in the project.
    match /databases/{database}/documents {
        // Handle users
        match /users/{documentId} {
            // The owner can do anything, you can access public data
            allow read: if (isOwner() && isEmailVerified()) || isPublic();
            allow write: if isOwner() && isEmailVerified();

            // Functions //
            function isSignedIn() {
                return request.auth != null;
            }

            function isOwner() {
                return request.auth.uid == resource.data.userId;
            }

            function isPublic() {
                return resource.data.userId == "public";
            }

            function isEmailVerified() {
                return request.auth.token.email_verified
            }      
        } 
    }
}