rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /messages/{messageId} { // anyone can read messages allow read: if true; // anyone can create a message // text must exist and be under 240 characters allow create: if request.resource.data.text is string && request.resource.data.text.size() <= 240; // the only update allowed is an echo // echoCount and lastEchoAt fields can be changed // this prevents anyone from editing the text of someone else's message allow update: if request.resource.data.diff(resource.data) .affectedKeys().hasOnly(['echoCount', 'lastEchoAt']); // nobody can delete messages through the client allow delete: if false; } // --- global "memory counter" (GlobalCountPill) ------------------------- // a single shared doc, meta/stats, holding totalMessagesEverPosted. // anyone can read it (it's shown to every visitor); writes are limited to // just that one field, same "only these fields can change" pattern as the // echoCount update rule above, so this doc can't be hijacked to store // arbitrary data. match /meta/stats { allow read: if true; // first-ever write: only the counter field, and it must be a number allow create: if request.resource.data.keys().hasOnly(['totalMessagesEverPosted']) && request.resource.data.totalMessagesEverPosted is number; // every later write (increment(1)) may only touch that same field allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(['totalMessagesEverPosted']); // nobody can delete the counter through the client allow delete: if false; } } }