Allow use of the filter value on whereArrayContains within a firestore rule
I believe that by simply allowing access to the whereArrayContains filter value, it should be possible to solve for a use-case which can generally only be resolved using an SQL/relational database or cloud functions.
Take the following query;
getDocs(
query(
collection(db, "profiles"),
where("groupProfileLinkIdReference", "array-contains", "groupProfileLinkId1"),
limit(1),
),
)
If we can access the value which in this case is "groupProfileLinkId1", it becomes possible to do the following;
match /profiles/{profileId} {
allow list: if validateListProfileDbEntry();
}
function validateListProfileDbEntry(){
let groupProfileLinkId = resource.data.groupProfileLinkIdReference[0];
let groupProfileLink = get(/databases/$(database)/documents/groupProfileLink/$(groupProfileLinkId)).data;
return groupProfileLink.isApproved == true;
}
The way the data is modelled is that every time a new groupProfileLink is created for a profile the groupProfileLinkId is added to the profile's groupProfileLinkIdReference array field.
Db summary;
profiles
- profileId1
- id: "profileId1"
- title: "someProfile"
- groupProfileLinkIdReference: ["groupProfileLinkId1", "groupProfileLinkId2"]
...
groupProfileLinks
- groupProfileLinkId1
- id: "groupProfileLinkId1"
- groupId: "groupId1"
- profileId: "profileId1"
hopefully this makes sense - it really seems like it would unlock many new possibilities
-
Rob Molloy commented
I still think this is a good idea but it can be resolved using a map instead of an array;
```
getDocs(
query(
collection(db, "profiles"),
where(`groupProfileLinkIdReference.${groupProfileLink1.id}`, "==", "groupProfileLinkId1"),
limit(1),
),
) -
Rob Molloy commented
I didn't want to pollute the above request but potentially you would need to duplicate the id on each doc in the profiles collection. This would ensure you are returning only the correct profile. The query would like this;
```
getDocs(
query(
collection(db, "profiles"),
where("id", "==", "profileId1"),
where("groupProfileLinkIdReference", "array-contains", "groupProfileLinkId1"),
limit(1),
),
)
```