firestore - strategy for server based validation?

2,252 views
Skip to first unread message

Martin Kuhn

unread,
Oct 20, 2017, 10:18:18 AM10/20/17
to Firebase Google Group
I am curious how to handle server side validation of my data when using firestore...

In a traditional approach with a REST based backend I would (of course) do my validation (and maybe enhancement) before I store the data in a DB.

When I use e.g. the convenient UI libs (e.g. angular fire) I don't use REST but the UI lib methods to manipulate data.

Now I am aware of firestore "triggers". But I don't see something like a "beforeWrite" where you would be able to veto a data update (from my point of view this would be the most elegant way to handle this)

The other approach would be to use "rules" to validate, right? But this seems that is has big limitations... (no real programm code, no possibility to enhance / manipulate data)

And, of course, I could use a cloud function which is called in a REST way and do the update in a "traditional" way (but than I loose the benefits of the client lib)


So what would be the way to go? How do you handle this stuff?



Kato Richardson

unread,
Oct 20, 2017, 11:29:19 AM10/20/17
to Firebase Google Group
Martin,

You'll find that security rules are quite powerful and capable. This becomes particularly clear when you catch on to the idea that you can use the existing data in the database to write additional logic, such as role based access, etc (e.g. `get(/myCollection/otherDocument).data.field == value;`).

However, if you have some advanced game logic or server-side data manipulation, then you are going to need backend code. There's no way around this. Functions is of course a great solution to managing those isolated snippets of app logic.

☼, Kato

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-talk+unsubscribe@googlegroups.com.
To post to this group, send email to fireba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/e8428d37-d2b3-4339-8aa6-28f0361641a0%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Kato Richardson | Developer Programs Eng | kato...@google.com | 775-235-8398

Michael Bleigh

unread,
Oct 20, 2017, 3:57:05 PM10/20/17
to Firebase Google Group
There are lots of strategies to manage this, for example:
  1. Use security rules (you'll get further than you think, as Kato mentioned)
  2. Use an HTTP function to intermediate the request (this is the traditional model, but is still sometimes appropriate)
  3. Write to one location, use a function to validate/decorate and then write the "confirmed" data to a different location or delete if rejected
  4. Use rules to handle validation, have a function side effect that updates the doc in-place with additional info and marks as "ready"
Each of these approaches have tradeoffs. In general I'd recommend trying to get as far as you can without functions (1) and then when necessary use functions for side effects (4).

On Fri, Oct 20, 2017 at 8:29 AM 'Kato Richardson' via Firebase Google Group <fireba...@googlegroups.com> wrote:
Martin,

You'll find that security rules are quite powerful and capable. This becomes particularly clear when you catch on to the idea that you can use the existing data in the database to write additional logic, such as role based access, etc (e.g. `get(/myCollection/otherDocument).data.field == value;`).

However, if you have some advanced game logic or server-side data manipulation, then you are going to need backend code. There's no way around this. Functions is of course a great solution to managing those isolated snippets of app logic.

☼, Kato
On Fri, Oct 20, 2017 at 5:57 AM, Martin Kuhn <marti...@gmx.at> wrote:
I am curious how to handle server side validation of my data when using firestore...

In a traditional approach with a REST based backend I would (of course) do my validation (and maybe enhancement) before I store the data in a DB.

When I use e.g. the convenient UI libs (e.g. angular fire) I don't use REST but the UI lib methods to manipulate data.

Now I am aware of firestore "triggers". But I don't see something like a "beforeWrite" where you would be able to veto a data update (from my point of view this would be the most elegant way to handle this)

The other approach would be to use "rules" to validate, right? But this seems that is has big limitations... (no real programm code, no possibility to enhance / manipulate data)

And, of course, I could use a cloud function which is called in a REST way and do the update in a "traditional" way (but than I loose the benefits of the client lib)


So what would be the way to go? How do you handle this stuff?



--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.

To post to this group, send email to fireba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/e8428d37-d2b3-4339-8aa6-28f0361641a0%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--

Kato Richardson | Developer Programs Eng | kato...@google.com | 775-235-8398

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.

To post to this group, send email to fireba...@googlegroups.com.

Leonardo Gutiérrez

unread,
May 25, 2018, 11:03:26 AM5/25/18
to Firebase Google Group
I also have this concern, and the suggested approches don't quite fulfill the need. Let´s say for example, I need to assure that a date type is sent in x field, is there anything that will prevent me from sending just a random string other than client side validation? Considering that it's a good practice to validate data on the client and server side.

I might need to change paradigm for serverless architecture, since I don't see a solution other than the "beforeWrite" pipeline suggested by Martin.

Kato Richardson

unread,
May 25, 2018, 1:18:53 PM5/25/18
to Firebase Google Group

See Timestamp and String.matches. You should be able to match pretty much any date format you want.

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To post to this group, send email to fireba...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Kiptoo Magutt

unread,
Jul 6, 2020, 8:22:21 AM7/6/20
to Firebase Google Group
Yeah a *beforeWrite* trigger would be very nice, we can run ORM-based validation and data manipulation if this feature were available.

I am struggling with using security rules because:
  1. It seems to lack granularity (instead of returning validation errors on specific fields, they just return a blanket PERMISSION DENIED error so it's hard to debug and do any additional data manipulation). Most importantly, I'm not able to tell my users which specific form fields failed validation (I'd have to also do client-side validation everywhere, which is OK but it's a bit redundant)
  2. The syntax is a bit verbose IMO - having to do request.resource.data.population just to get the field (and a few times if I have to check its type, value range, etc) is not ideal really

Sam Stern

unread,
Jul 6, 2020, 8:58:52 AM7/6/20
to Firebase Google Group
Hi Kiptoo,

Thanks for the feedback.  We won't be adding "beforeWrite" Cloud Functions triggers to Cloud Firestore but we do understand your concerns.

Also it's worth nothing for (2) that you can now use "let" bindings in Rules, for example:

function isDataValid() {
  let data = request.resource.data;
  return data.foo && data.bar == "baz";
}

- Sam

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.

Kato Richardson

unread,
Jul 6, 2020, 3:58:10 PM7/6/20
to Firebase Google Group
You can achieve beforeWrite now by just calling the function directly and letting it decide if the write is allowed, rather than trying to write to Firestore and asking the Functions to intercede later. This iis a much more scalable solution than delaying database writes in order to call Functions triggers; that would seriously impede the realtime and strongly consistent nature of Firestore.

☼, Kato

Kiptoo Magutt

unread,
Jul 13, 2020, 10:00:03 PM7/13/20
to Firebase Google Group
Thanks Sam, noted.

I tried the 'let' binding exactly as you described but I'm getting this error:

Error compiling rules:
L57
:11 Missing 'match' keyword before path.
L58
:7 Unexpected 'let'.
L58
:7 mismatched input 'let' expecting {'{', '/', PATH_SEGMENT}
L202
:1 Unexpected '}'.

I am using rules version '2' and my code looks like this:

rules_version = '2'

// ...

// Fetch a user from Firestore
function getUserData(userCollName) {
return get(/databases/$(database)/documents/users/$(request.auth.uid)).data
}

// users collection
match /users/{company} {
 let userData = getUserData();
 allow read: if isSignedIn();
 allow write: if false;
}
// ...


Might you know what is wrong with my rules code?
To unsubscribe from this group and stop receiving emails from it, send an email to fireba...@googlegroups.com.

Kato Richardson

unread,
Jul 14, 2020, 12:30:43 PM7/14/20
to Firebase Google Group
We'll need the complete rules file to help here as it's related to a specific line of the syntax and probably caused by something coming prior to the line noted.

To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/36206ca0-8a5d-4414-b4cb-2f4e84a9ac52o%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages