Right appraoch to prevent duplicates in db

Viewed 27

I would like to prevent user/hacker from :

  1. Writing a document with a doc name that already exist ( docs names are custom strings not Auto UserIDs)
  2. Writing a document that contains an email field that already exist.

Assuming i can't normalize the database ( there are too many requirements and normalizing one ruin the other).

Can i create rules for these ? especially number 2 ?

Or, should i instead create a Cloud Function that do that after reading DB, without any rule ?

Which approach is more "right" ?

1.
    
    Docs
      John:{}
      Johnny:{}
      John:{} // *** prevent another john

2. 
   Docs
    abcd:{email:xyz}
    efgh:{email:xyz}  // *** prevent this one
2 Answers

After some reading, I realized that the best way to go is to do all of those inside a Firebase Function, then everything is well protected ( Function check duplicates before write).

Since this is done only once, on a user registration ( e.g when he choose a special nick name) it sounds reasonable to search on a DB for duplicates. This is done once in a user lifetime.

Checking in Rules if there is another document with a certain field, or even a certain custom doc name, is impossible and "not scalable".

Denormalize the DB is an option, but many times doing so will prevent from another field to be searchable, and you don't want to create so many collections.

  1. Should be tested

    match /col/{docid} {
      allow create: if !exists(/databases/$(database)/documents/col/$(docid))
    }
    
  2. Not possible as such, you can access another document from a rule if you know the full path of this doc, but you cannot make an SQL-like join as the one you want. An alternative would be to use the email as the docid, this way you can just use the same solution as 1 above.

Related