I have a users collection that looks like:
/users/{userId}
that has an array of maps that looks, for example, like
blockedUsers: [
{user: "1", userName: "un1", displayName: "dn1"},
{user: "4", userName: "un4", displayName: "dn4"}
]
I've denormalized the banned user data to simplify things. I'm trying to setup firestore rules to prevent a banned user from replying to messages by the user that banned/blocked them.
here's my rule I've setup, which doesn't work but I've spent quite a while trying to figure this out and am now turning to StackOverflow for help.
match /users/{user} {
allow read: if request.auth != null;
allow create: if request.resource.id == request.auth.uid;
allow update: if request.auth != null && !resource.data.blockedUsers.hasAny[request.auth.uid];
}
Update Here's the client side code that a user would use to reply:
const processNewMessage = async (evt, newMessage) => {
myMessage.value = myMessage.value.trim();
if (evt.srcElement.textContent === "send") {
if (replying.value === true) {
const message = {
originalMessage: {
text: props.selectedMessage.text,
photoUrl: props.selectedMessage.photoUrl,
},
reply: {
user: uid,
userDisplayName: auth.currentUser.displayName,
userName: userName.value,
text: newMessage,
createdAt: Timestamp.now(),
photoUrl: photoUrl,
},
};
await updateDoc(doc(db, `users/${props.selectedMessage.user}`), {
replies: arrayUnion(message),
});
}
}
}
Please let me know if I'm missing any necessary info.
!resource.data.blockedUsers.hasAny[request.auth.uid]
cannot work since the blockedUsers
array is an array of compounded objects (or maps).
The object/map { displayName: 'Kamal', uid: 'U4Tuy6676...', userName: 'Kamal' }
is not equal to the string 'U4Tuy6676...'
.
I would suggest you duplicate your data and have another array only containing the blocked uids. It will be easier than building the map in the security rules (I'm even not sure that you can do so: AFAIK you will not be able to get the userName
value from the ID token).