Determine whether a list of paths contains a dynamic path - firebase

I have a function in my firebase rules file userRolesIncludesPermission, this function checks a property on the user to determine whether that user has a certain permission on their role, it does so by comparing references.
This works as expected in the firebase rules file when used for security rules for firestore. Unfortunately this does not work as expected with "storage".
After research I found out that the problem is the comparison between the references from the permissions list under user.data.roles[0] and my custom made path.
Is there any better way to produce a path that can be recognizable using a list function?
Is it an unknown limitation of storage security rules?
Note that the function getRootCollectionDocRef works perfectly when I try to build a queryable path even in the same request (for example when I try earlier in the code to query the user)
Another note is that in the rules playground (console debugger) it works. But in an actual request from the website (dev, for now) it doesn't.
function getRootCollectionDocRef(collection, docId) {
return /databases/(default)/documents/$(collection)/$(docId);
}
function userRolesIncludesPermission(user, permissionId) {
return firestore.get(user.data.roles[0]).data.permissions.hasAll([getRootCollectionDocRef("permissions", permissionId)]);
}
I tried to use every available list function such as "in", "hasAny" etc.
I tried to build the path while converting it with path() function.
I tried to convert to a set.
I tried to use a hard coded non-dynamic path. It failed as long as I use a custom-made path.
However when trying to query the path with a fixed index (i.e firebase.get(permissions[1]) it worked. But this is an invalid practice. I have to make it dynamic, but the problem is that I can't loop over the list and convert the paths to strings on the fly.
Thanks in advance!!

Related

Executing a method which is named via a config file

In short: I have a method name provided via a JSON configuration file. I'd like to call a method using this provided name. The method (with a matching name) will exist in the backend. What's the best way of going about this?
I am not quite sure what I should be searching for as an example.
To detail: I am working with a legacy application, hence the VB.NET. I am building a single PDF file from multiple PDF sources. Most of these are as is, I simply read the configuration and grab the relevant files and the job is done. However some require processing, I'd like the configuration file to pass in a method name to be called that will perform extra processing on the PDF, whatever that may be.
As there can be a lot of PDF files that can vary, I cannot simply use a property such as "PostProcessing: true".
Any ideas?
You could use reflection to reflect method names back and check them against the name passed from the property in the config file.
Like so
Type magicType = Type.GetType("MagicClass");
MethodInfo magicMethod = magicType.GetMethod("ItsMagic");
object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100});
That would work.. but to be honest, I'd go with a case statement as you'll be hardcoding the method names anyway (because they are code), and it'll be strongly typed (less chance of typos and errors).

Firestore security rules: get() use in hasAny() list method

I was wondering if this security rule would be possible:
function productForUser() {
return resource.data.products.hasAny(get(/databases/$(database)/documents/Users/$(request.auth.uid)).data.products);
}
When I try to test it in the testing plaground on the Firebase website, it is sucessful. However, when I try to run it with Javascript, with this query, I get the read denied, with "missing or insufficient permissions":
query.where("products", "array-contains", productId);
I can confirm that the user has the array of products, containg the specific product that is being looked up in the query.
Thanks in advance.
Your rule works in the console simulator because the simulator only supports "get" type requests for a single document. It doesn't work for queries because security rules are not filters. The rule will not be evaluated for each and every document in the collection, as that would not scale well at all for very large collections. To specify conditions for queries, you will need to provide exact values to check from the client - you will not be able to use a get() to find other values.
If you want to test queries before publishing your rules, you should not be using the simulator, and instead use the local emulator to test code that actually performs a query.

How do you manage adding new attributes on existing objects when using firebase?

I have an app using React + Redux and coupled with Firebase for the backend.
Often times, I will want to add some new attributes to existing objects.
When doing so, existing objects won't get the attribute until they're modified with the new version of the app that handles those new attributes.
For example, let's say I have a /categories/ node, in there I've got objects such as this :
{
name: "Medical"
}
Now let's say I want to add an icon field with a default of "
Is it possible to update all categories at once so that field always exists with the default value?
Or do you handle this in the client code?
Right now I'm always testing the values to see if they're here or not, but it doesn't seem like a very good way to go about it. I'd like to have one place to define defaults.
It seems like having classes for each object type would be interesting but I'm not sure how to go about this in Redux.
Do you just use the reducer to turn all categories into class instances when you fetch them for example? I'm worried this would be heavy performance wise.
Any write operation to the Firebase Database requires that you know the exact path to the node that you're writing.
There is no built-in operation to bulk update nodes with a path that is only partially known.
You can either keep your client-side code robust enough to handle the missing properties, or you can indeed run a migration script to add the new property to each relevant node. But since that script will have to know the exact path of each node to write, it will likely first have to read/query the database to determine those paths. Depending on the number of items to update, it could possibly use multi-location updates after that to update multiple nodes in one call. E.g.
firebase.database().ref("categories").update({
"idOfMedicalCategory/icon": "newIconForMedical",
"idOfCommercialCategory/icon": "newIconForCommercial"
"idOfTechCategory/icon": "newIconForTech"
})

global variable in optaplanner

In drools rule file how do I set the value of (or initialize) a global variable for optaplanner. My use case is following:
I want to declare a global java map that is constant and will not change during the execution. Every rule will access the map to check for a value, if value is in the map then rule will evaluate to false. The map is being generated before execution starts by accessing data in files/database.
This link https://issues.jboss.org/browse/PLANNER-94 is also requesting the access to global variable but this feature is rejected now.
How do i use the hack defined in this link: Setting global variables in working memory in Drools planner, from which object i should get CustomSolverPhaseCommand? [I am not able to comment on this post yet because i don't have enough reputation, sorry if it seems duplicate question].
I am creating SolverFactory from xml Resource and xml file contains the path to .drl file. Just like in .drl we can access object HardSoftScoreHolder scoreHolder, I want to access the map in the same way in 'then' part of rule.
can anyone please help?
Look at the examples that have a class that ends with Parameterization instead, such as ConferenceParametrization, this is probably a better alternative than globals.

Sails.js: How to properly handle request parameters/queries to backend?

I'm developing an application using Sails.js in the backend, and I'm having trouble validating requests as follows:
I want to block access to certain resources based on an attribute of the logged in user. I have the REST API blueprints enabled, and the shortcut routes disabled. I have the following piece of code:
User.findOne()
.where(query)
.exec(function(err, user) {
if (user.team !== req.user.team) {
return res.view('403');
}
return next();
});
where query is the criteria by which I'd like to do the database search. The idea is that the user can only access the requested user if they're in the same "team".
The problem is that the user can make at least the following kinds of requests to the backend, maybe more (I'm not too experienced with sails, please enlighten me if there's even more types):
localhost:1337/user?id=1
In this case, the req object will have a req.query attribute, which I can pass on as query as it is. Now, the following kind of request is also possible:
localhost:1337/user/1
Here req.query will be an empty object, while req.params is [ id: '1'].
Now this is troublesome; if I understand correctly, the the type of req.params isn't a JSON object, so I can't pass it as query as it is. In addition, I'd have to convert the id parameter into Int since it's originally a string for some reason (?).
What I'm asking is if there's a way I may have missed that handles both kinds of requests in the same way, or whether I'll have to take both cases into account in a way like
var query = isEmpty(req.query) ? req.params : req.query
in which case I'd have to convert req.params into something I could pass to the database search and would generally be troublesome and inconvenient. I'd like to know what the best way to handle this situation is.
Well, it's funny how right after posting a question you happen to find an answer. Apparently there's a function called req.allParams() which "Includes parameters parsed from the url path, the query string, and the request body." according to the official docs. I've no idea how I never bumped into this before, but now I did and it seems to work, so hooray!

Resources