Meteor Session.get and Regex - javascript

Is there any possibility (in Meteor) to get all Session keys and match them with Regex? like
Session.set( /(?:^|\W)word-(\w+)(?!\w)/g , false )
I want set them all to false. But i know only first word in key name, and it is always the same.

Session is not designed to work with regexp. On the other hand you can easily use client-side collections for storing information of this type. So
var mySession = new Meteor.Collection(null); // null is important!
mySession.update({key: {$regexp: /* regexp */}}, {$set: {value: false}});
Remember that Collection is a reactive data-source just like Session, so this will behave almost identically as Session in terms of templates rendering. The only difference is that the data from mySession will be erased after hot code push. This can be fixed by using reload or amplify package but it is quite a different story.

Related

Firestore range query - matching rules to "where" clauses

I'd like to query a Firestore collection based on a string field, returning all documents where that field starts with a custom claim on the user's auth token. I was able to use this answer to create a query using >= and < operators with a successor key, and this works well for me when my I relax my Firestore rules.
I'd like to lock down my ruleset so that a user only has access to documents that start with their custom claim.
I've read the rules are not filters literature, and from my understanding of it, I just need to write rules such that my query can never return data that would violate the rules.
So that's what I'm attempting to do without much success:
I have a Firestore collection with documents that look something like this:
{
"id": 1,
"namespace": "foo.bar"
}
Each user has a custom claim on their auth token, let's say it's my_namespace.
I wrote a Firestore rule like so:
function hasNamespaceAccess(request, resource){
//allow if data.namespace starts with request.token.my_namespace
return resource.data.namespace.matches(request.auth.token.my_namespace + ".*");
}
match /path_to_my_objects/my_collection/{my_obj} {
allow read, write: if hasNamespaceAccess(request, resource);
}
My query, after simplifying to make this post as concise as I can, looks like this:
return db
.collection('my_collection')
.where('namespace', '>=', 'foo.') //the namespace "query values" are hard coded for clarity here
.where('namespace', '<', 'foo.c')
The token which is used when making a call to Firestore does, for sure, have "my_namespace": "foo"
What I Expect
My Firestore rules says that a user has access to any document where namespace starts with "foo" -- the doc with "namespace": "foo.bar" conforms to this.
My query should only return documents where namespace is between "foo." and "foo.c". Again, my document conforms to this. This query, I believe, can never return a document that does not conform to the regex string in my Firestore rule.
As such, I'd expect to get a result set with my document.
What actually happens
index.cjs.js:13448 Uncaught Error in snapshot listener: FirebaseError: Missing or insufficient permissions.
at new n (index.cjs.js:129)
at index.cjs.js:10175
at index.cjs.js:10176
at n.onMessage (index.cjs.js:10209)
at index.cjs.js:10115
at index.cjs.js:10146
at index.cjs.js:5542
I've tried modifying my query to not use a range, and to only have where("namespace", "==" "foo.bar"), and this works as expected, so it seems like the rest of the system is working fine, but there is a mismatch between the rules and the filter clause.
The problem here is not that your code is trying to access data that the rules don't allow, but that the rules engine isn't smart enough to be able to prove that for all cases of a match without having to check the actual data.
An interesting alternative would be to perform the same check with >= and <= operators. I didn't have a chance to try that though, so let me know if that works (or doesn't work) for you.

Firestore says I have inequality filter on multiple properties, when I don't

I am trying to do a "small hack" to avoid reading the User document everytime the page loads. So I save it locally, everytime the page loads I get the local version, get the updated_at property and then do something like WHERE last_updated > {{updated_at}}. For that, I want to use this:
firebase.firestore().collection('User')
.where(firebase.firestore.FieldPath.documentId(), '==', firebase.auth().currentUser.uid)
.where('updated_at', '>', updated_at)
.get()
As you can see, I have one equality (==) and one inequality (>). Why do I get the following error on the console:
FirebaseError: Cannot have inequality filters on multiple properties: updated_at
at new t (https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:47054)
at t.fromRpcStatus (https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:116660)
at t.fromWatchChange (https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:125914)
at t.onMessage (https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:242411)
at https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:241212
at https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:241997
at https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:144869
I am doing this to try to avoid reading from the database if the local version is the same as the one in the database. Maybe if you have a better way, please let me know.
Thanks
firebaser here
The equality check you have on documentId() is internally converted into a range check by Firestore, because the keys are stored as the last items in existing indexes (if I understand correctly). And that means that server-side you're trying to perform two inequality/range checks, which isn't allowed.
So the behavior you are seeing is correct. But it's definitely not intuitive, and the error message is also not helpful. We'll look for a way to improve the error message by detecting this combination.
I had the same problem and I implemented the following hack: I added the id as part of the field name on which I made the check for the latest version. If your logic allows you to do that, for you this would mean:
firebase.firestore().collection('User')
.where(id + '_updated_at', '>', updated_at)
.get()
This allows to bundle in just one where statement both the check on the id and on the date (documents with different ids wont have the field id + '_updated_at' and wont therefore be selected).
Worked like a charm for me

Is it possible to use ES6 Symbols in LocalStorage

When using a ES6 Symbol as the key for a key/value pair in LocalStorage, can we then still access it after reloading the page?
I found this tutorial that claims this to be possible when using Symbol.for, but so far I have no success and get an undefined when I try to retrieve the LocalStorage key/value pair.
As a side question: does it make sense to use Symbols over here?
You can use Symbols as keys in an object - that's one of theirs purposes. But localStorage is not your typical object. It has an API to set/get values in the store, which the tutorial you have shared is not using: localStorage.{set,get}Item().
Unfortunately localStorage doesn't accept Symbols as keys, only strings. So the real answer is no, you can't use Symbols as keys in LocalStorage, but...
You could do the following. It isn't actually using a Symbol as the key, but the Symbols toString() representation:
const sym = Symbol.for('Hello').toString()
localStorage.setItem(sym, 'World')
document.write('Hello, ' + localStorage.getItem(sym))
[ Check it out on jsbin.com ]
As a side question: does it make sense to use Symbols over here?
I suppose you could use reserved Symbols (e.g. Symbol.iterator) to extend the functionality of the localStorage global. But that's kind of besides the point.

Vert.x Equivalent to the Node.js Global object

In Node.js you can assign values to keys off of the global object. This gives you the ability to "remember" something between requests. Assuming the node.js process doesn't die/hang and restart by a process like iisnode.
Does Vert.x have an equivalent? Essentially, I'm looking for the simplest possible cache for a piece of data so I do not have to fetch it on every request. I assume the solution on Vert.x may be able to work across threads?
the code:
{{id:1,name:"Yahoo"},{id:2,name:"Google"}}
break cause it's not valid json,you can use
{companies : [{id:1,name:"Yahoo"},{id:2,name:"Google"}]} //notice than they are inside an array
now..the doc says
To prevent issues due to mutable data, vert.x only allows simple immutable types such as number, boolean and string or Buffer to be used in shared data
that means, maybe you will need use
var map = vertx.getMap('demo.mymap');
map.put('data', JSON.stringify({companies : [{id:1,name:"Yahoo"},{id:2,name:"Google"}]}))
and then in other verticle
var map = vertx.getMap('demo.mymap');
var yourJSON = JSON.parse(map.get('data');
now..maybe a good option which would be use redis like a cache system, although the vertex map seems solve your needs so far...

How to parse JSON dynamically in iOS

We used a third party service and it provides a JS file.
The js file launches an http request and get a json.We parsed the json and got the content we wanted but the json format always changes.
Is there a way to parse the json but do not update our app?
It sounds awful stupid to constantly change schemas, but anyway, maybe you could try having a manifest somewhere in the cloud that translates the latest schema keywords into one your app understands?
Basically, I presume that the info in the JSON is similar (otherwise it wouldn't make sense at all) and only the keywords change. You could have a JSON you constantly update that translates the keywords used in the app into the newest one used by the webservice.
So an example would look like this. Imagine this is the format you are used to when developing the app (this is the one app expects).
{
"name" : "Henri",
"title" : "iOS Developer"
}
Now if the webservice changes it's schema and returns something like this
{
"key1" : "Henri",
"key2" : "iOS Developer"
}
You should have a manifest.json which translates it like this
{
"name" : "key1",
"title" : "key2"
}
I hope you get where I'm going with this, basically you can shift the translation to the cloud, giving you the chance to keep it up to date while app remains the same. So after loading in the translation you can access the data like this
NSString *name = [actualJSON objectForKey: [manifestJSON objectForKey: #"name"]];
The JSON home page has quite a bit of materials on the subject which should allow you to develop your own parser if you wish. There are also some ObjectiveC parsers available down at the bottom of the page.
http://www.json.org/
For this purpose we looked at Cocoa's standard key path infrastructure but weren't particularly happy with how it combines with arrays and dictionaries. In the end I ended up writing my own little key-path lookup thing, essentially like:
- (id)objectAtPath:(NSString *)path inObject:(id)object
{
// accept an input string like key1.key2.key3.index.key4.etc;
// so we'll split on the dots and use each separate component
// to navigate the object graph
NSString *components = [path componentsSeparatedByString:#"."];
for(NSString *component in components)
{
if([object isKindOfClass:[NSDictionary class]])
{
// if this is a dictionary, use this component as
// a key into the dictionary
object = [object objectForKey:component];
}
else
if([object isKindOfClass:[NSArray class]])
{
// if this is an array, use this component
// as an index into the array
NSInteger index = [component integerValue];
// treat out of bounds indices as finding nil
// rather than raising an exception
if(index < 0 || index >= [object count]) object = nil;
else object = [object objectAtIndex:index];
}
}
}
So you might call objectAtPath:#"shoes.4.typeOfLaces" inObject:jsonResult if 'jsonResult' is a dictionary to get the array 'shoes', the dictionary at index 4 in the array and then whatever value that dictionary has for the key 'typeOfLaces'.
The production code actually has some smarter navigation aids, allowing you to say things like "take whichever object in this array of dictionaries has the largest value for the key 'size'" or "take the object with type=large if it exists, otherwise take any object", but exactly what you want to do there will depend on your app and the variability of the schema.
Once you're navigating object graphs by key path, you can just grab the current key paths from a server somewhere, allowing you to change how JSON is navigated on device without submitting a new binary.
The only warning I'd add is to be careful how much functionality you put into your key paths. Apple don't allow fresh code to be downloaded so whatever you do you don't want to end up at anything that Apple could construe as a scripting language, no matter how restricted.

Categories

Resources