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));
}