I have a use case where I have documents of type Channels, Users and Content, like a number of blogs, for example.
TL;DR: I need help creating a rule which can have multiple users get access to do queries on subsets of documents (like 'admins'). Not just one user and not just all documents.
A user can have its uid as part of the 'admins' map property of a Channel document, and only then will the user able to edit properties. The following rule works fine for this;
match /channels/{channelId=**} {
allow read, write: if request.auth.uid in get(/databases/$(database)/documents/channels/$(channelId)).data.admins;
}
When content is added to a channel, the only thing I can get working is to add content objects to an array in the channel document. I would like to use firestore queries, naturally so I've tried both to use a sub-collection under the channel object and a separate root collection and I cannot compose a security rule to work.
The rule should match a user whose uid is a member of the admins map property on the channel document to be allowed to read and write to a content object.
The content object has a 'channelRef' property which contains the id of the channel document whose admins map property should be matched with the uid of the request.auth object.
My last try of very many was the following rule;
match /content/{contentId=**} {
allow read, write: if exists(/databases/$(database)/documents/channels/$(get(/databases/$(database)/documents/content/$(contentId)).data.channelRef)/admins/$(request.auth.uid));
}
I'm trying to use get() to force getting a reference to the content document (since resource.data.xxxx sometimes fails for some reason..)
- My Content document look like this; {channelRef: 'ccc'}
- My Channel document 'channels/ccc' look like this; {admins:['uuu']}
- The uid of the user is 'uuu'
I have also tried to use a sub-collections for admins under the channel, where the path would look like 'channels/ccc/admins/uuu' and using exist() instead. No dice.
I have verified that I can access a content document by direct reference (like using firestore.doc('content/123')..) but not using a query. Also, there is only one content document in the collection, so there is no possibility of the query hitting another document which is not allowed.
The query looks like this (with type 'content', property 'channelRef' and value 'ccc';
let ref = firestore.collection(this.type)
let query = ref.where(this.property, this.operation, this.value)
query.onSnapshot((res)=>
{
...
Any help very much appreciated.