Config variables not being resolved in middleware.json in Loopback 3 - loopbackjs

I'm unable to get the restApiRoot variable to resolve when using it in middleware.json. I'm using Loopback 3. Here's my setup:
config.json
{
"restApiRoot": "/api"
}
middleware.json
"auth": {
"./middleware/order-auth": {
"paths": [
"${restApiRoot}/Orders"
]
}
},
If I replace ${restApiRoot} with /api then it works. I found this issue which sounds identical, but their resolution was to update loopback and loopback-boot back in 2016, and my versions are well beyond this. My middleware.json matches my version (3) docs.

I believe that loopback-boot performs variable substitution only when } is the last character. See the source code in lib/plugin-base.js (loopback-boot version 3.x):
var DYNAMIC_CONFIG_PARAM = /\$\{(\w+)\}$/;
function getConfigVariable(app, param, useEnvVars) {
var configVariable = param;
var match = configVariable.match(DYNAMIC_CONFIG_PARAM);
// etc.

Related

Extract a regex capturing group with rego

I'm trying to build a rule based file access "engine", that evaluates whether a service is allowed to access a file or not via rego rules/data.
Here's what I have so far
data
{
"bucketname": "randombucket"
"bucketpaths": {
"service1": "/base/path/in/bucket"
}
"rules": {
"service1": {
"GET": ["/storage/service1/(.*)"]
// ^ This is basically a relative path and I'd like to extract it
}
}
}
rego rule
package org.test
import future.keywords.if
import future.keywords.in
default allow := false
default ttl := 60
basePath = data["bucketpaths"][input.ServiceType]
default relativePath := ""
allow if {
allowedPaths := data["rules"][input.ServiceType][input.Method]
some allowedPath in allowedPaths
regex.match(allowedPath, input.Path)
# here I would like to do three things:
# 1) check if the regex matches
# 2) extract the capuring group
# 3) set the value into relativePath
}
fullPath = concat(basePath, relativePath)
bucketName = data["bucketname"]
input
{
"ServiceType": "service1",
"Method": "GET",
"Path": "/storage/service1/a/relative/path"
}
Here's a link to the rego playground: https://play.openpolicyagent.org/p/3p7VAxwTcR
Disclaimer, I'm a noob to opa/rego, so these statements probably don't make any sense to experienced people...
I already tried using regex.find_all_string_submatch_n but I just cannot wrap my head around two things basically
I'm inside of an if statement, which is obviously not meant to set values - but how else would I do it?
How do I "just run a piece of code" to evaluate stuff "somewhere"? To - for example - evaluate the regex and just assign the result

MongoDB: Aggregation using $cond with $regex

I am trying to group data in multiple stages.
At the moment my query looks like this:
db.captions.aggregate([
{$project: {
"videoId": "$videoId",
"plainText": "$plainText",
"Group1": {$cond: {if: {$eq: ["plainText", {"$regex": /leave\sa\scomment/i}]},
then: "Yes", else: "No"}}}}
])
I am not sure whether it is actually possible to use the $regex operator within a $cond in the aggregation stage. I would appreciate your help very much!
Thanks in advance
UPDATE: Starting with MongoDB v4.1.11, there finally appears to be a nice solution for your problem which is documented here.
Original answer:
As I wrote in the comments above, $regex does not work inside $cond as of now. There is an open JIRA ticket for that but it's, err, well, open...
In your specific case, I would tend to suggest you solve that topic on the client side unless you're dealing with crazy amounts of input data of which you will always only return small subsets. Judging by your query it would appear like you are always going to retrieve all document just bucketed into two result groups ("Yes" and "No").
If you don't want or cannot solve that topic on the client side, then here is something that uses $facet (MongoDB >= v3.4 required) - it's neither particularly fast nor overly pretty but it might help you to get started.
db.captions.aggregate([{
$facet: { // create two stages that will be processed using the full input data set from the "captions" collection
"CallToActionYes": [{ // the first stage will...
$match: { // only contain documents...
"plainText": /leave\sa\scomment/i // that are allowed by the $regex filter (which could be extended with multiple $or expressions or changed to $in/$nin which accept regular expressions, too)
}
}, {
$addFields: { // for all matching documents...
"CallToAction": "Yes" // we create a new field called "CallsToAction" which will be set to "Yes"
}
}],
"CallToActionNo": [{ // similar as above except we're doing the inverse filter using $not
$match: {
"plainText": { $not: /leave\sa\scomment/i }
}
}, {
$addFields: {
"CallToAction": "No" // and, of course, we set the field to "No"
}
}]
}
}, {
$project: { // we got two arrays of result documents out of the previous stage
"allDocuments" : { $setUnion: [ "$CallToActionYes", "$CallToActionNo" ] } // so let's merge them into a single one called "allDocuments"
}
}, {
$unwind: "$allDocuments" // flatten the "allDocuments" result array
}, {
$replaceRoot: { // restore the original document structure by moving everything inside "allDocuments" up to the top
newRoot: "$allDocuments"
}
}, {
$project: { // include only the two relevant fields in the output (and the _id)
"videoId": 1,
"CallToAction": 1
}
}])
As always with the aggregation framework, it may help to remove individual stages from the end of the pipeline and run the partial query in order to get an understanding of what each individual stage does.

Postman - How can I pass array as variable

Is there the possibility to use an array variable inside postman?
e.g. inside the body of a request:
{
"myData" : {{arrayVariable}}
}
and inside the data file:
{
"arrayVariable": ["1", "2", "3"]
}
It's possible, you can even add your own keys
You can create a JSON body like this:
{
"myData" : [
{{arrayVariable}}
]
}
And the variable like this:
arrayVariable: "1", "2", "3"
where arrayVariable is the key and "1", "2", "3" is the value.
using variable with a same name will give you an array
Postman environment variables are meant to just save data as string, so here you are the workaround to pass array as environment variable/data file to Postman as a string like this:
{
"arrayVariable": '["1", "2", "3"]'
}
Then, add the following piece of code to parse this variable in pre-request script in Postman like this:
var x = JSON.parse(postman.getEnvironmentVariable("arrayVariable"));
postman.setEnvironmentVariable("arrayVariable", x);
Please create your body request like below
{
"myData" : ["{{arrayVariable}}"]
}
and there is no change required for data file.you can use as it is.
{
"arrayVariable": ["1", "2", "3"]
}
It will work definatly.
The only solution worked for me was something like the answer MickJagger provided, but I think it needs some clarifications.
The JSON data file should be something like this:
[
{
"anArray": "1, \"2\", 3.0, \"Foo\", false"
}
]
which it's value is a string, escaping the quotations for string elements.
(Note that this example differs from example provided by original question, to cover more use cases.)
The variables is as MickJagger said:
{
"value": [{{anArray}}]
}
Maybe other solutions works on previous postman versions, but this solution is tested on postman's latest version (by the time of publishing this answer), i.e. v7.34.0 .

AWS DynamoDB Scan filterExpression - simple number comparison

I am trying to do a simple dynamoDB scan with a filter expression (documentation here)
This is my expression string:
"attribute_exists("my_db_key") AND ("my_db_key" = 1)"
This simply states:
"If a value for my_db_key exists AND my_db_key EQUALS 1, return it in the results"
However it does not work and I get a this error:
Invalid FilterExpression: Syntax error; token: "1", near: "= 1)
I am aware that I can use an attribute value placeholder for values and then use that in the expression but I do not want to do this. And according to Amazon's documentation it is NOT required.
So how do I do this simple expression? Does anyone have an example or link to documentation? Amazon's documentation is unfortunately of no help.
NOTE: I am implementing this with AWSDynamoDBScanInput on iOS but my issue here is to do with global expression syntax so it should not matter.
Your params need to look something like this (for the Node AWS library):
params = {
"FilterExpression": 'attribute_exists("my_db_key") AND ("my_db_key" = :value)',
"ExpressionAttributeValues": {
":value": 1
},
// ...
};
docClient.scan(params, function(err, data){
// Handle err or process data
})
For some languages, the parameters should look more like this:
{
"FilterExpression": 'attribute_exists("my_db_key") AND ("my_db_key" = :value)',
"ExpressionAttributeValues": {
":value": {"N":1}
},
// ...
};
You have to use a placeholder and pass the value separately. Here's some documentation and a Post from AWS forums

'like' or $regex query inside $cond in MongoDB

Please go through this question of mine:
MongoDB $group and explicit group formation with computed column
But this time, I need to compare strings, not numbers.The CASE query must have a LIKE:
CASE WHEN source LIKE '%Web%' THEN 'Web'
I then need to group by source. How to write this in Mongo? I am trying the following but not sure if $regex is supported inside $cond. By the way, is there a list of valid operators inside $cond somewhere? Looks like $cond isn't very fond of me :)
db.Twitter.aggregate(
{ $project: {
"_id":0,
"Source": {
$cond: [
{ $regex:['$source','/.* Android.*/'] },
'Android',
{ $cond: [
{ $eq: ['$source', 'web'] }, 'Web', 'Others'
] }
]
}
} }
);
There're many other values that I need to write in there, doing a deeper nesting. This is just an example with just 'Android' and 'Web' for the sake of brevity. I have tried both with $eq and $regex. Using $regex gives error of invalid operator whereas using $eq doesn't understand the regex expression and puts everything under 'Others'. If this is possible with regex, kindly let me know how to write it for case-insensitive match.
Thanks for any help :-)
Well, it still seems to be not even scheduled to be implemented :(
https://jira.mongodb.org/browse/SERVER-8892
I'm using 2.6 and took a peek on 3.0, but it's just not there.
There's one workaround though, if you can project your problem onto a stable substring. Then you can $substr the field and use multiple nested $cond. It's awkward, but it works.
Maybe you can try it with MapReduce.
var map = function()
{
var reg1=new RegExp("(Android)+");
var reg2=new RegExp("(web)+");
if (reg1.test(this.source)){
emit(this._id,'Android');
}
else if (reg2.test(this.source))
{
emit(this._id,'web');
}
}
var reduce = function (key,value){
var reduced = {
id:key,
source:value
}
return reduced;
}
db.Twitter.mapReduce(map,reduce,{out:'map_reduce_result'});
db.map_reduce_result.find();
You can use JavaScript regular expresions instead of MongoDB $regex.