Firestore-Rules evaluation error on Timestamp Field - firebase

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?

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

Having problems using && and/or || and reprogram the NthRoot function

So I am suppose to Use && and/or || and reprogram the NthRoot function. The NthRoot Function code is this:
NthRoot<-function(m,n) {
if(!is.integer(n)!=1) {
stop("Error: N must have length 1. Go away.")
}
else if (!is.integer(n) | is.numeric(n)) {
return(m^1/n)
}
else
stop('Error: You must input an interger or vector of intergers.
Existing...\n\n')}
When I replace if and else if, with double & and double |, I receive an error message, Error: unexpected '&&' in:
"NthRoot<-function(m,n) {
&&". I am having a hard time understanding this part of R programming so I'm struggling a lot. Any help is greatly appreciated. Thank you

Recursion with return types

How to understand complex recursions? I just find the beginner level recursion examples. I wanted to know how to understand recursion and the call stack when complex logic is involved.
public Boolean recursion(int value, string name)
{
if (value > 10 && value<12)
return false;
if (value > 110)
return false;
if (value > 104 && value < 106)
return false;
return recursion(value+1,"left") || recursion(value+100,"right");
}
or to be precise the following logic
public bool HasPathSum(TreeNode root, int sum) {
if (root == null)
return false;
if (root.val == sum && (root.left == null && root.right == null))
return true;
return HasPathSum(root.left, sum - root.val)
|| HasPathSum(root.right, sum - root.val);
}
How do i understand the flow of the above sample recursive function?
Recursion is a little tricky, you need to keep track every time the function is called. In each invocation, a separate stack is made.
Specifically, for the second function, it is checking if the sum of the root to leaf path nodes is equal to particular value. The OR || condition is there because the path can either be in left or right subtree - if any one satisfies it s a true.
The line if (root.val == sum && (root.left == null && root.right == null)) checks that till you reach the leaf, is the sum equal to the value. Also notice that the value is decreased and then used to call recursively, because a node is considered and its value has been taken into consideration, the rest of the nodes from this node to the leaf must have the sum less than the original sum ( less by the current node's value ).

Collection deny rule property undefined

When invoking this in the browser console:
Meteor.users.update({_id:'2MA7iPq7bNtfxGm6r'},{$unset:{'profile.taskInProgress':''}})
This Meteor server code is giving this error
TypeError: Cannot read property 'profile.taskInProgress' of undefined
Meteor.users.deny({
update: function (userId, doc, fields, modifier) {
const tasks = ['search', 'aSearch'];
return (!(
userId &&
userId == Meteor.userId() &&
(tasks.indexOf(modifier.$set['profile.taskInProgress']) >= 0) || //<--comment for next line to work
(modifier.$unset['profile.taskInProgress'] == '') // <-- or comment for the above line to work
));
}
});
it works if I comment out the "error line", but if I do that then I will loose the permission to $set it. So now it appears like I can have one or the other but not both permissions. Must be some problem with my code.
How to allow the client to unset the 'profile.taskInProgress' property?
i think you have a logic problem.
your expression is basically this:
!(a && b && c || d)
c is valid only when you're doing a $set, and d is valid only when you're doing an $unset.
if your expression were this (without the prefixing bang):
(a && b && c || d)
... then, for a $set, the evaluation will be: a, b, c. if those are all true, then the condition is satisfied. it does not need to proceed to evaluation of d. that's good, because i think that would fail due to lack of null check.
but if $unset is used, then i believe that c will fail, because of a lack of null check. (i'm not positive here, but i think that's what's going on).
but, you have the entire expression "notted". that's going to force evaulation of each of a, b, c, and d, regardless of whether $set or $unset is being used. and this will always fail due to lack of null checks.
what you really mean, i think, is:
!(a && b && (c || d))
as written, you could not have a userId, and as long as d is true (and null checks were in place), you would allow the operation.
to solve it, i would break out the evaulation from the overall logic. e.g.
let userIdExists = !!userId;
let requesterIsLoggedInUser = (userId === Meteor.userId());
let progressSet = (modifier.$set && (tasks.indexOf(modifier.$set['profile.taskInProgress']) >= 0));
let progressUnset = (modifier.$unset && (modifier.$unset['profile.taskInProgress'] == ''));
let allowed = userIdExists && requesterIsLoggedInUser && (progressSet || progressUnset);
let denied = !allowed;
return denied;
i tend to be verbose in logic situations like this, to ensure each condition is easily understood.
btw, why is this not expressed as an allow rule? returning "allow" instead of "!allowed" in a deny seems easier to read, imho.
edit: the allow version simply does a "return allowed;" at the end, instead of bothering with the denied variable.
if you're trying to debug, console.log() out all the vars to see if they're what you expect. if you want, update your question w/ those results and console logs of modifier so it's easier to confirm the logic for progressSet and progressUnset.

how will the precedence of && and != work in a logical statement?

While (ptr ! =NULL && dptr! = NULL && dptr->next! =NULL)
In this code if the pointer dptr is NULL will it work or will terminate?
If the statement is true or not is actually based not only on dptr but also on ptr and dptr->next. If the statement is true - the content if the while-loop will be executed.
The substatements (your camparisons to not NULL) are checked one after another - if one is false, the other will not be executed. This is true for most programming languages. Though I haven't checked with all.
Logical && as well as || have some inherent mechanism for fast return. They both go step by step from left to right substatement. (Plus () ). With && the check is aborted on the first false statement. With || the check is aborted on the first true statement. The other checks won't be reached.
So your statement will never check dptr->next != NULL for the case that dptr is actually NULL. So your statement is safe from access to NULL pointers.

Order of evaluation of conditionals in actionscript 3.0 (Flex)

var btn:Button;
if(btn != null && btn.label != '') {
mx.controls.Alert.show("d");
}
In the above if clause, is it guaranteed that the first condition(btn != null) will
be evaluated before the second condition?
Yes - ActionScript performs appropriate short-circuiting for the && operator:
http://www.adobe.com/support/flash/action_scripts/actionscript_dictionary/actionscript_dictionary013.html
So not only will it evaluate the expressions in the order you described, it won't bother evaluating the second expression at all if the first one returns false (which is as important a detail as the order of evaluation).
Just as a note, ActionScript also supports short-circuiting the logical or operator (||).
Yes it is. Excerpts from the Adobe livedocs regarding && operator:
&& logical AND Operator:
Usage:
expression1 && expression2
Returns expression1 if it is false or can be converted to false, and expression2 otherwise.

Resources