Firestore data validation rule does not work

this is my first question on stackoverflow.

I am trying to write some simple Firestore security/data validation rules, to prevent creating a user that has an age less than 18.

This is what I have until now:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if
          request.time < timestamp.date(2021, 9, 22);
    }

    match /users/{user} {
      allow create: if request.resource.data.age > 18;
    }
  }
}

The code that I use to write data to Firestore is the following:

const firebase = require('firebase');

require('firebase/firebase-firestore');

const firebaseConfig = {/* firebase api keys */}

firebase.initializeApp(firebaseConfig);

const Firestore = firebase.firestore();

Firestore.collection('users')
  .add({
    first_name: 'Laura',
    last_last: 'Waterson',
    age: 5,
  })
  .then((docRef) => {
    console.log('Document written with ID: ', docRef.id);
  })
  .catch((error) => {
    console.error('Error adding document: ', error);
  });

As you notice, I am adding a user that has age equals 5, and it is actually added to the database meaning that the security rule I wrote does not work.

Am I doing anything wrong ?

Answer

Your /users collection is covered by two rules: the second rule that explicitly names the collection, but also by the first rules that applies to all documents in all collections and subcollections under the root.

According to the documentation on overlapping match statements in the documentation:

It’s possible for a document to match more than one match statement. In the case where multiple allow expressions match a request, the access is allowed if any of the conditions is true:

So the statements are OR’ed together, not AND’ed. Since your first rule already evaluates to true, it doesn’t really matter what your second rule does anymore.

You’ll want to remove/comment out the first rule, so that your code is checked against the second rule.