Home > Software design >  Firestore-Rules evaluation error on Timestamp Field
Firestore-Rules evaluation error on Timestamp Field

Time:11-23

I wrote a firestore rule like this:

function isPublished() {
  return !('publicationAt' in resource.data.keys()) ? true :
    debug(debug(request.time) >= debug(resource.data.publicationAt));
}

and in my app i´m saving several datetimes just with new Date(); Now, I´d like to get a list of all items that are published - but it gives me an evaluation error - with this debug:

constraint_value {
simple_constraints { comparator: LTE value { timestamp_value { seconds: 1669108946 nanos: 684000000 } }
} }

timestamp_value { seconds: 1669108945 nanos: 727000000 }

Can someone give me a hint what I´m doing wrong?

CodePudding user response:

While you may be tempted to think that Security Rules Language (SRL) is JavaScript because of the function() {} part, it is not. It is a special statically evaluated language that gets interpreted once without other common features like iteration.

Importantly, the SRL has no ternary operator:

<condition> ? <result-when-true> : <result-when-false>

Instead you must build your conditions as a sequence of Boolean tests making use of the available helper methods and classes.

The equivalent in basic Boolean algebra of the ternary operator (when using short-circuiting operators like && and ||) is:

(<condition> && <result-when-true>) || (NOT(<condition>) && <result-when-false>)

Substituting in the value for <result-when-true>, we can reduce down your expression using Boolean algebra laws (where the AND operator (&&) is and the OR operator (||) is ):

(<condition> && <result-when-true>) || (NOT(<condition>) && <result-when-false>)

// replace <result-when-true> with TRUE, as in your question
(<condition> && TRUE) || (NOT(<condition>) && <result-when-false>)

// now remove the redundant "&& TRUE" (see "Identity of ∧")
<condition> || (NOT(<condition>) && <result-when-false>)

// now distribute the OR operator (see "Distributivity of ∨ over ∧")
(<condition> || NOT(<condition>)) && (<condition> || <result-when-false>)

// now replace (<condition> || NOT(<condition>)) because it will always be TRUE (see "Complementation 2")
TRUE && (<condition> || <result-when-false>)

// now remove the redundant "TRUE &&" like before (see "Identity of ∧")
<condition> || <result-when-false>

Subsituting in the parts from your question, this leaves us with:

   !('publicationAt' in resource.data.keys())
|| debug(debug(request.time) >= debug(resource.data.publicationAt))

You can also simplify 'publicationAt' in resource.data.keys() to just 'publicationAt' in resource.data (as the in operator handles what you were expecting for rules.Map objects), giving us:

   !('publicationAt' in resource.data)
|| debug(debug(request.time) >= debug(resource.data.publicationAt));

This means the correct form of your SRL function would look like:

function isPublished() {
  return !('publicationAt' in resource.data)
      || debug(debug(request.time) >= debug(resource.data.publicationAt));
}
  • Related