Firebase 如何为特定集合编写基于身份验证的Firestore规则

Firebase 如何为特定集合编写基于身份验证的Firestore规则,firebase,google-cloud-firestore,firebase-authentication,firebase-security,Firebase,Google Cloud Firestore,Firebase Authentication,Firebase Security,我有一个名为Orders的集合,还有另外两个为用户和驱动程序的集合。我希望Orders集合只能由Drivers集合中的UID访问 所有登录到应用程序的人都是用户,但是驱动程序是唯一可以访问订单文档的用户 逻辑是检查用户是否已签名,以及Drivers集合是否包含包含该用户UID的字段。如果集合字段包含该用户的UID,则他可以访问该文档集合 allow write, read: if isSignIn() & `Driver colletion contains that user UID`

我有一个名为
Orders
的集合,还有另外两个为
用户
驱动程序
的集合。我希望
Orders
集合只能由
Drivers
集合中的UID访问

所有登录到应用程序的人都是用户,但是
驱动程序
是唯一可以访问
订单
文档的用户

逻辑是检查用户是否已签名,以及
Drivers
集合是否包含包含该用户UID的字段。如果集合字段包含该用户的UID,则他可以访问该文档集合

allow write, read: if isSignIn() & `Driver colletion contains that user UID`
我如何才能做到这一点,如果可以,我需要一些帮助来编写代码

这是我的规则,我没有改变太多。我只知道这段代码适用于我数据库中的每个文档,所以我需要编写一些细节

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow write, read: if isSignIn();
    }
    
    function isSignIn(){
    return request.auth != null;
    }
    
  }
}
下面是我如何从Firestore获取数据的

func newOrders(){
        
        let fireStore = Firestore.firestore()
        let doc = fireStore.collection("Orders")
        
        self.driverListener = doc.addSnapshotListener { (query, err) in
            if err != nil {
                print(err?.localizedDescription ?? "")
            }
            guard let querysnap = query else {return}
            
            querysnap.documentChanges.forEach({ change in
                
                if change.type == .added {
                    
                self.DriverOffers = []
                for document in querysnap.documents{
                        
                    let snap = document.data()

                guard let orderLoc = snap["orderLocation"] as? GeoPoint else {return}
                    
                guard let docId = snap["docId"] as? String else {return}
                guard let name = snap["name"] as? String else {return}
                guard let phone = snap["phone"] as? String else {return}
                guard let time = snap["time"] as? String else {return}
                guard let marketName = snap["marketName"] as? String else {return}
                guard let price = snap["amount"] as? String else {return}
                guard let userImg = snap["userImg"] as? String else {return}
                guard let storeImg = snap["storeImg"] as? String else {return}
                guard let order = snap["order"] as? String else {return}
                guard let userid = snap["userUid"] as? String else {return}
                guard let timestamp = snap["date"] as? Timestamp else {return}
                let date = Date(timeIntervalSince1970: TimeInterval(timestamp.seconds))

                guard let userlocation = snap["userLocation"] as? GeoPoint else {return}

                    let offer = driverOrdersData(docId: docId, userUid: userid, name: name, phone: phone, amount: price, time: time, marketName: marketName, storeimgUrl: storeImg, userImgUrl: userImg, date: date, orderDetails: order, orderLocation: orderLoc, userLocation: userlocation, distance1: distance1, distance2: distance2 )
                    
                    self.DriverOffers.append(offer)
                    DispatchQueue.main.async {
                    self.DriverOrdersTV.reloadData()

                    }
                    }
                
            }
            }
        })
        
        }

}

您无法在安全规则中签入文档中是否存在具有特定值的文档,因为这将需要您的规则查询集合,而且成本高昂且无法扩展

实现此用例(以及许多其他用例)的诀窍是在
驱动程序
(可能还有
用户
)集合中使用用户的UID作为文档ID。您可以通过以下方式添加这些文档:

let uid = ....; // wherever you get the UID from
firebase.firestore().collection("Drivers").doc(uid).set({ uid: uid });
现在,使用该结构,您可以检查安全规则中是否存在具有特定UID的文档,这是可能的:

function isDriver() {
  return exists(/databases/$(database)/documents/Drivers/$(request.auth.uid))
}

另请参阅上的Firebase文档。

您可以分享屏幕截图中其他收藏的外观吗?@Dharmaraj我已经更新了quistion@Swift我看你没有接受我的回答。你能澄清一下它还缺少什么吗?在尝试了几天之后,这个答案实际上不起作用,我只是在XCode调试器中获得了文档的权限失败,但如果文档已经在本地缓存中,我仍然从集合@FrankVanpuffelle获取文档(例如:如果在缓存规则后更改了规则,或者为具有访问权限的其他用户读取了规则)缓存可能会返回文档,即使服务器没有返回。具体情况取决于您如何实现读取操作,您没有共享该操作,但由于这不应该是一个正常的用例,因此我建议卸载并重新安装应用程序,以清除在开发过程中发生的缓存数据。