I'm developing a simple app that can upload photos. I'm using firebase firestore and storage. Every time I upload a new photo I create an object like this:
struct Item: Codable, Identifiable {
var id: UUID // photo name
var uidOwner: String // uid user owner
var emailOwner: String // email user owner
var path: String // photo path
var shared: [String] = []
}
For now I'm just using this rules for checks that the user email is it contained in the "shared" data of every document.
enter rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /photos/{photo} {
allow read if: resource.data.emailOwner in get(/databases/$(database)/documents/photos/$(photo)).data.shared;
}}}
In Swift project I take this query:
enter func getItems() async throws -> [Item] {
do {
let querySnapshot = try await photoCollection
.whereField("emailOwner", arrayContains: user.email ?? "[email protected]")
.getDocuments()
let items = try querySnapshot.documents.compactMap { doc in
return try doc.data(as: Item.self)
}
return items
} catch {
throw error
}
}
I'm logging in with an email contained within the shared array in a document. Why doesn't that use have access?
Recognize that "Security Rules are not filters". The security rules do not look at the documents being returned by a request to determine the validity of the request. They look at the REQUEST itself to determine if the REQUEST is valid or not.
Your rule (if using Puf's answer) says:
allow read if: resource.data.emailOwner in resource.data.shared;
but your query is:
.whereField("emailOwner", arrayContains: user.email ?? "[email protected]")
So your query is says "if the array emailOwner
contains the following value (user.email ?? [email protected]
)"
Your query is looking at in emailOwner
but your rule is looking at in shared
.