I have notification records where there is a text and a list of users (max 10).
{text: "Beware of the dog", users: [ uid1, uid2, uid3, ... ]}
When a user read/acknowledge the notification, I want to remove him from the list of users who can see the notification (then he won't get any anymore).
For that, when the user press the "hide notification button", he send a request to update the notification record with:
users: FieldValue.arrayRemove(uid)
I want to enfore with security rules that the user:
Tried with
allow update: if
request.auth.uid != null
&& request.auth.uid in resource.data.users
&& request.resource.size() == 1
&& request.resource.data.users != null;
Any hint, help, idea well appreciated.
When you create a database or storage instance in the Firebase console, you choose whether your Firebase Security Rules restrict access to your data ( Locked mode ) or allow anyone access ( Test mode ). In Cloud Firestore and Realtime Database, the default rules for Locked mode deny access to all users.
Firebase Security Rules stand between your data and malicious users. You can write simple or complex rules that protect your app's data to the level of granularity that your specific app requires.
Allow only Firebase authenticated users with a verified email to read documents under the collection named documents: Allow a user to read or write only to the document that contains their user data. In this case, we do this by setting the document ID to the user authentication ID:
Realtime Database security overview The Firebase Realtime Database provides a full set of tools for managing the security of your app. These tools make it easy to authenticate your users, enforce user permissions, and validate inputs. Firebase-powered apps run more client-side code than those with many other technology stacks.
I had a similar situation and it was quite a brain teaser. This is what did the trick for me:
allow update: if
request.auth.uid != null
&& request.resource.data.diff(resource.data).affectedKeys().hasOnly([data])
&& request.resource.data.users.size() == resource.data.users.size() - 1
&& resource.data.users.removeAll(request.resource.data.users)[0] == request.auth.uid
Specifically:
data
uid
) from the old one with removeAll()
and returns an array with their difference. In this case, it returns an array which contains only the single uid
that you chose to arrayRemove()
. Then we simply check that uid
- which can only exist at position [0]
- and make sure it is equal to the uid
of the authenticated user.I don't think this is possible without a loop, which doesn't exist in security rules. Well: if you know all users, you might be able to enumerate all options, essentially unfolding the impossible loop. But even if this is possible in security rules, the rules are going to be incredibly verbose.
I'd recommend creating a subcollection where each UID is stored in a separate document. In that subcollection you can then implement your requirement by only allowing the user to only delete their own document.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With