Getting the user's timezone in KRL - krl

A follow-up question to Mike's question about getting the time in KRL. Is it possible to get the user's timezone? There is a timezone predicate,
time:timezone(<arg>)
but it looks like it requires an argument. How do I use that?

time:timezone(<arg>) is a predicate which returns true or false.
I will correct the documentation, but time:timezone() takes a timezone abbreviation and checks the user's geo-location (based upon IP address) and returns true or false
rule first_rule is active {
select when pageview ".*" setting ()
if (time:timezone("MST")) then {
notify("Glee alert", "Glee starts at 7pm");
}
}

Related

Vert.x WildcardPermissionBasedAuthorization .match returns false

I'm having trouble understanding how WildcardPermissionBasedAuthorization works (docs)
The following code returns false, which as far as I know means that the user is not authorized, though I would expect at least one of these 'or' authorizations to match the wildcard one of "t*"
User user = User.create(new JsonObject().put("username", "testUser"));
user.authorizations().add("", PermissionBasedAuthorization.create("test"));
user.authorizations().add("", WildcardPermissionBasedAuthorization.create("t*"));
OrAuthorization or = OrAuthorization.create();
or.addAuthorization(PermissionBasedAuthorization.create("t"));
or.addAuthorization(PermissionBasedAuthorization.create("te"));
or.addAuthorization(WildcardPermissionBasedAuthorization.create("t"));
or.addAuthorization(WildcardPermissionBasedAuthorization.create("te"));
or.addAuthorization(WildcardPermissionBasedAuthorization.create("te*"));
or.match(user); //is false
What I'm trying to achieve is give my user access to anything that starts with 't', and then in my handler assert whether the user has access to 'te'
thanks,
Fil
Ok, turns out you can put a wildcard for an entire colon-delimited section only, like
"newsletter:edit:*"
from here

Running into an issue with a mutation and component flickering with react-query

So, I am making a query everything my context API is updated via a form selection update..
So, order of operation is like so.
User makes a change to a form by selecting (one of possible many) from dropdown.
Change updates "context api" which resaturates the parent component.
Because the form key/values changed, I fire a mutation.
Mutation returns a value. So far, great.
But, when I repeat step #1 - #4, another component flickers with that updated value because at some point the "const" that is expecting a value is undefined... THEN, it has a value..
So, like so..
has a value...
...query api call...
has no value
...returns query
has a value
const ProductPage = (props) => {
const { question } = useContextStateWhatever();
/* Queries */
const { data = {}, isFetched } = useProductUpdatePrice({ questions });
const value = derivePriceFromResponse(data.products);
return (
<SomeComponentRendered value={value} />
)
So, you can see between the "old value" and request in query, that the passed "value" will be undefined. Then query returns, updated value.
I was hoping the query will return any previous value, but the "queryKey" changes with every selection of the form. Deep queryKey.
I was hoping I wouldn't have to then put this value into local state from within a useEffect, or use useRef and create hook to hand back "previous" value until new value is ready.... That's not what react-query is for, right? I mean, shouldn't I be able to make a query call whenever the "context api" changes, and not expect this latency diff of undefined. Any strategies to over come this?
Since the "queryKey" is different (mostly for normal form interaction) for each query, I can see how it can't hand back a previous value until it resolves etc.. any ideas?
Any thoughts?
I think the keepPreviousData: true option is what you are looking for. If the query key changes, you will the get the data from the previous query key, along with an isPreviousData: true flag. The background update will still happen, and then you’ll get the data for the new query key once it arrives. The query will stay in isSuccess status the whole time.

How is "after" and "before" method implemented in Google Spanner truetime?

According to their pager, it says "The TT.after() and TT.before() methods are convenience wrappers around TT.now()."
And according to What is the TrueTime API in Google's Spanner?
It also provides two functions:
after(t) returns true if t has definitely passed. E.g. t < now().earliest.
before(t) returns true if t has definitely not arrived, or t > now().latest.
My question are:
On all servers in spanner, does TT.now() return the same result?
For a given time t, is possible that on server A before(t) is true and on server B is false?
Are they monotonic? e.g. On server A, TT.after(t) is true, sometime later, is it possible that TT.after(t) is false?
For details of how Truetime and Spanner work, look at section 3 of the Spanner Whitpaper (1).
A discussion of how it could be implemented is in the question "Why is Google's TrueTime API hard to duplicate?" (2)
From the Spanner Whitepaper, a TrueTime value is not a single value but a timestamp range which is guaranteed to contain the absolute value. This range takes into account the potential clock drift - which in Google's network, with syncing the server clocks to the atomic/GPS reference time every 30secs is up to 7ms (from the whitepaper).
So if TTstamp1 is the range (t1_lo, t1_hi) and TTstamp2 is the range (t2_lo, t2_hi), then before() and after() simply compare the extremes of these ranges to confirm that they do not overlap.
TTstamp1.before(TTValue2) = t1_hi < t2_lo
TTstamp1.after(TTValue2) = t1_lo > t2_hi
The answer to your questions are therefore:
No, TT.now() does not return the same result on all servers even if called at the exact same instant. However the values obtained on all servers when called at that instant will overlap each other, meaning that none of them are before nor after each other.
So for a given TrueTime t, it is technically possible that on server A t.before(now) is true and on server B t.before(now) is false due to the overlap comparison and the differences between the possible ranges. This is not an problem for Spanner because it will wait until there is no overlap (t.before(now)==true) before committing a transaction and storing its timestamp.
(Note: this information is derived from the public whitepapers and documentation)
According to the picture below , TT.after(t) is TT.now().earliest > t, so I think it's quite possible that TT.before(t) is TT.now().latest < t.
Try to answer my own question:
TT.now() does not return the same result on all servers at the same time.
Yes, it's possbile. Even though for case of TT.after(),this means time t has definitely passed only on some servers.
I don't know. If it is possbile, then it means t has definitely passed, and then not sure about that, which sounds a little weird
I think "definitely" in their description is a little misleading, they should simply be "higher than the latest" or "lower than the earliest”

How does resource.data.size() work in firestore rules (what is being counted)?

TLDR: What is request.resource.data.size() counting in the firestore rules when writing, say, some booleans and a nested Object to a document? Not sure what the docs mean by "entries in the map" (https://firebase.google.com/docs/reference/rules/rules.firestore.Resource#data, https://firebase.google.com/docs/reference/rules/rules.Map) and my assumptions appear to be wrong when testing in the rules simulator (similar problem with request.resource.data.keys().size()).
Longer version: Running into a problem in Firestore rules where not being able to update data as expected (despite similar tests working in the rules simulator). Have narrowed down the problem to point where can see that it is a rule checking for request.resource.data.size() equaling a certain number.
An example of the data being passed to the firestore update function looks like
Object {
"parentObj": Object {
"nestedObj": Object {
"key1": Timestamp {
"nanoseconds": 998000000,
"seconds": 1536498767,
},
},
},
"otherKey": true,
}
where the timestamp is generated via firebase.firestore.Timestamp.now().
This appears to work fine in the rules simulator, but not for the actual data when doing
let obj = {}
obj.otherKey = true
// since want to set object key name dynamically as nestedObj value,
// see https://stackoverflow.com/a/47296152/8236733
obj.parentObj = {} // needed for adding nested dynamic keys
obj.parentObj[nestedObj] = {
key1: fb.firestore.Timestamp.now()
}
firebase.firestore.collection('mycollection')
.doc('mydoc')
.update(obj)
Among some other rules, I use the rule request.resource.data.size() == 2 and this appears to be the rules that causes a permission denied error (since commenting out this rules get things working again). Would think that since the object is being passed with 2 (top-level) keys, then request.resource.data.size()=2, but this is apparently not the case (nor is it the number of keys total in the passed object) (similar problem with request.resource.data.keys().size()). So there's a long example to a short question. Would be very helpful if someone could clarify for me what is going wrong here.
From my last communications with firebase support around a month ago - there were issues with request.resource.data.size() and timestamp based security rules for queries.
I was also told that request.resource.data.size() is the size of the document AFTER a successful write. So if you're writing 2 additional keys to a document with 4 keys, that value you should be checking against is 6, not 2.
Having said all that - I am still having problems with request.resource.data.size() and any alternatives such as request.resource.size() which seems to be used in this documentation
https://firebase.google.com/docs/firestore/solutions/role-based-access
I also have some places in my security rules where it seems to work. I personally don't know why that is though.
Been struggling with that for a few hours and I see now that the doc on Firebase is clear: "the request.resource variable contains the future state of the document". So with ALL the fields, not only the ones being sent.
https://firebase.google.com/docs/firestore/security/rules-conditions#data_validation.
But there is actually another way to ONLY count the number of fields being sent with request.writeFields.size(). The property writeFields is a table with all the incoming fields.
Beware: writeFields is deprecated and may stop working anytime, but I have not found any replacement.
EDIT: writeFields apparently does not work in the simulator anymore...

Access 2013: I am trying to return today's date when a yes/no fields is marked as "Yes"

I am trying to return today's date in a date field when another field is marked as "Yes". I tried the following expression but to no avail. I have limited experience with expressions and greatly appreciate any guidance. If the field does not have a "Yes" the date field can be blank. I cannot set the default to "No" for the Approved field.
Approved Date: IIf([Approved]=True,Today(),Null)
If I set the date, it will work but the date is dynamic so this is not really helpful.
Approved Date: IIf([Approved]=True,5/1/2016,Null)
Thank you in advance for your help.
OK, so I spent a little time looking at how to do this with an expression. The answer is you can't, at least not without a helper function. So, my hybrid solution is:
1) Create a function in a standard module:
Public Function SetControlValue( _
ByVal ctlControl As Access.Control, _
ByVal varValue As Variant, _
Optional ByVal varTest As Variant = True)
If (varTest) Then
ctlControl.Value = varValue
End If
End Function
2) In the AfterUpdate event for the Approved checkbox, enter:
=SetControlValue([ApprovedDate],Date(),([Approved]=True) AND (IsNull([ApprovedDate])))
This approach saves you from making a class module under the form. And you can keep all such code in a common module, so you can build a library of such functions for other forms.
(old answer 2)
Based on your answers, what you can do is add an AfterUpdate event to the Approved control, which does something like:
Private Sub Approved_AfterUpdate()
If (Approved.Value = True) And IsNull(ApprovedDate.Value) Then
ApprovedDate.Value = Date()
End If
End Sub
This will set the approved date once, when the approved checkbox is first checked. If you need different behavior, this can easily be modified.
(old answer 1)
I think you have it backwards.
When [Approved] is set to True, set [ApprovedDate] = Today(). That way, it is saved to the table, and you have a permanent record of when it was approved.