Is it possible to limit to size of a List in Reads - playframework-2.6

My controller receives a json. One of the elements in the json is an array of strings. I have written the following validation for the json
implicit val pQ:Reads[PQ] = (
(JsPath \ "id").readNullable[UUID] and
(JsPath \ "description").read[String] and
(JsPath \ "h").read[List[String]] and
(JsPath \ "i").read[List[String]] and
(JsPath \ "s").read[String] and
(JsPath \ "t").read[Set[String]] and
)(PQ.apply _)
Is it possible to write a Reads or Validate such that the json gets rejected if the size of a List is more than a specified value (say the size of i list should not be more than 3?

I might write another answer where the code is more functional and organised. Happy to accept other answers as well.
The way to customize validating json is to extend Reads trait and implement its reads method.
abstract def reads(json: JsValue): JsResult[A]
I want to achieve two things
1) validate the the json has all the required fields
2) ensure that some of the fields have max-size limit (eg. no. of images which could be sent).
Json validation works by calling validate or validateOpt method of JsValue. These methods expect an implicit Reads and pass the JsValue to it.
def validate[T](implicit rds: Reads[T]): JsResult[T] = rds.reads(this)
So to validate json and map it to my PQ class, I had to create a Reads[PQ]. But because I want validation beyond just the structure of the json, I have to extends Reads and implement my own reads.
To do step 1, I created Reads[PQ] the normal way (just checking that all the required fields are present and can map to my PQ class
implicit val pQStructurallyCorrect:Reads[PQ] = (
(JsPath \ "id").readNullable[UUID] and
(JsPath \ "description").read[String] and
(JsPath \ "h").read[List[String]] and
(JsPath \ "i").read[List[String]] and
(JsPath \ "s").read[String] and
(JsPath \ "t").read[Set[String]] and
)(PQ.apply _)
To add step 2, I created another Reads[PQ] by extending Read[PQ] and by overriding the reads
implicit object PQReads extends Reads[PQ] {
def reads(json:JsValue):JsResult[PQ] = {
//check that the structure of the json is correct by utilizing the Reads created for step 1
val structurallyValidated = json.validateOpt[PQ](pQStructurallyCorrect)
structurallyValidated match {
case JsSuccess(pQOpt,path)=>{ //structure is correct. now check content
val result = pQOpt.map(pq=>{
if(pq.image.length <0 || pq.image.length > 3)
{
JsError("invalid no. of images")
}
else {
JsSuccess(pq)
}
}).getOrElse(JsError("Error in validating Json"))
result
}
case JsError(errors) =>{
JsError(errors)
}
}
}
}
Now to validate the json, I use PQReads object
implicit val qReads:Reads[Q] = (JsPath \ "p-q").read[PQ](PQReads)
.map((x:PQ)=>Q.apply (x))
What is happening above is when my application receives the json,
1) It first gets the body as json from the incoming request
val jsonBodyOption = body.asJson
2) Then the json is validated
val qOption = jsonBody.validateOpt[Q] //this uses qReads:Reads available implicitly
qReads uses PQReads to validate the json. PQReads first calls validateOpt passing pQStructurallyCorrect which checks the structure. If the structure is correct, then the length of image List is checked.

Related

Can someone point me in the right direction to begin parsing this string in dart?

I have a series of string like this:
(((S|69|L || S|69|R || S|72|L || S|72|R) && ((S|62|L && (S|78|L || S|55|L) && (S|77|L || S|1|L)) || (S|62|R && (S|78|R || S|55|R) && (S|77|R || S|1|R)))) && (M|34|L || M|34|R) && (((M|40|L && M|39|L && M|36|L) || (M|40|R && M|39|R && M|36|R)) || ((M|38|L && M|36|L && M|37|L) || (M|38|R && M|36|R && M|37|R))))
And I need to run items that look like S|69|L to see if they satisfy this criteria. You can see that it's a series of && or || operations organized by parentheses.
I'm trying to use this tutorial: https://github.com/petitparser/dart-petitparser
But I'm having trouble getting off of the ground. Can anyone give me an example to get started with this? Maybe I just need more coffee...
Update: Making progress. This at least pulls off outside parentheses. I think I just need to continue to play with it, but I would still appreciate any tips for those who know how this works.
String testString = '((1||2) || 3)';
final inner = undefined();
final paren = (char('(').trim() & inner.star().flatten() & char(')').trim())
.map((values) => values[1]);
inner.set(paren | pattern('^)'));
final parser = inner.end();
final result = parser.parse(testString);
print(result.value);
The grammar you provide in the question seems to work for me and the provided example inputs pass.
A couple of tips:
If you are not interested in the parser output, instead of calling parser.parse(input) you could use parser.accept(input) to get a boolean.
Similarly, if you are not interested in the output, you can drop the calls to flatten() and map(...). Both are used to build an AST. Furthermore, flatten() hides the generated tree, which can make it hard to see what is happening.
For the actual values you could use a primitive parser like the following. However, not sure what your exact specification is?
final primitive = (uppercase() & char('|') & digit().plus() & char('|') & uppercase()).flatten().trim();
If you have the primitive parser, you can add an undefined parser for the logical expression (called outer) like so:
final outer = undefined();
final inner = undefined();
final operator = string('&&') | string('||');
outer.set(inner.separatedBy(operator));
final paren = char('(').trim() & outer & char(')').trim();
inner.set(paren | primitive);
final parser = outer.end();
Building expression parsers can get complicated and unwieldy quite quickly. With the Expression Builder this becomes much simpler:
final builder = ExpressionBuilder();
builder.group().primitive(primitive);
builder.group()
.wrapper(char('(').trim(), char(')').trim(), (l, v, r) => [l, v, r]);
builder.group()
..left(string('&&').trim(), (a, op, b) => [a, '&&', b])
..left(string('||').trim(), (a, op, b) => [a, '||', b]);
final parser = builder.build().end();

Ruby - Array value is stored with a different Unicode character

Ruby is storing array value as ["118\u001F119"] as a result I'm unable to get the first index value.
Any idea how I can retrieve the value properly?
prov = $evm.root['miq_provision_request'] || \
$evm.root['miq_provision'] || \
$evm.root['miq_provision_request_template']
job_template_array = prov.get_option_array(:job_template_id)
job_template_array = job_template_array[0]
#handle.log(:info, "job_template_by_id is #{job_template_array}")
Here is the output when I try to get the first index.
[----] I, [2022-07-06T09:05:14.492607 #314:2aad21d5b6fc] INFO -- automation: Q-task_id([r745_miq_provision_1962]) <AEMethod launch_ansible_job> job_template_by_id is 118▼119
Here is what the function looks like.
def self.get_option_array(key, value, from)
# Return value - Support array and non-array types
data = value || from[key]
Array.wrap(data)
end

Odata File Download / get_stream method doesnt work

I have an oData service for File Download functionality. I have to include $value parameter to oData call to trigger GET_Stream at backend.
I see with an external breakpoint on get_stream method, that the method is triggered. But the file download doesn't work. I get a HTTP response 200 which means it is all OK but I don't see any data or row of information. The response in /IWFND/GW_CLIENT is empty.
So I debug and see that at the end of the get_stream method there is a parameter changing with these lines:
COPY_DATA_TO_REF(
EXPORTING IS_DATA = LS_STREAM
CHANGING CR_DATA = ER_STREAM)
In ls_stream there should be two columns (column1 and column2).
One of the columns is set and the other is empty. No matter what value I give to column2, it is still empty. Maybe I don't get any information at /IWFND/GW_CLIENT request because the parameter column2 is empty? Can you give me a suggestion?
My redefined methods are:
_DPC_EXT:
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_STREAM
ATTACHMENTSET_GET_ENTITYSET
_MPC_EXT:
DEFINE
I'm not sure what are these two components column1 and column2 you are referring to...
To return a PDF, you must define the entity type as being "Media" (checkbox), and transfer the PDF through the type /iwbep/if_mgw_appl_types=>ty_s_media_resource (components value of type XSTRING and mime_type).
More information in SAP Library > SAP Gateway Foundation Developer Guide > Media Links.
Example:
OData service ZGETPDF, with entity type File of type "Media" (and entity set FileSet)
URL to query the PDF: https://server.company.com:44322/sap/opu/odata/sap/ZGETPDF_SRV/FileSet('notused.pdf')/$value
ZCL_ZGETPDF_DPC_EXT class:
GET_STREAM method:
METHOD /iwbep/if_mgw_appl_srv_runtime~get_stream.
DATA: ls_stream TYPE /iwbep/if_mgw_appl_types=>ty_s_media_resource.
ls_stream-value = get_dummy_pdf( ).
ls_stream-mime_type = 'application/pdf'.
copy_data_to_ref( EXPORTING is_data = ls_stream
CHANGING cr_data = er_stream ).
ENDMETHOD.
Code to get a dummy PDF (any PDF, just for demo):
METHODS get_dummy_pdf RETURNING VALUE(result) TYPE xstring.
...
METHOD get_dummy_pdf.
" PDF from http://www.tagg.org/pdftest.pdf University of Liverpool
DATA(base64_string) =
'JVBERi0xLjIgDQol4uPP0w0KIA0KOSAwIG9iag0KPDwNCi9MZW5ndGggMTAgMCBSDQovRmlsdGVyIC9GbGF0ZURlY29kZSANCj4+'
&& 'DQpzdHJlYW0NCkiJzZDRSsMwFIafIO/we6eyZuckTZPtbtIWBi0UjYKQGxFbJmpliuLb26QM8X6CJBfJyf99ycmFF6xJagWrrMxz'
&& 'wJeCEMd+gFjWBC1dLPeCJFkbl/fTKfwnTqt1CK0xIZyEwFYZ2T+fwT8KnmIxUmJinNKJyUiyW7mZVEQ6I54m2K3ZzFiupvgPaee7'
&& 'JHFuZqyDvxuGBbZdu8D1y+7jYf+2e//C2KOJm9dxfEqqTHMRXZlR0hRJuKwZau6EJa+MOdjpYN/gprq8xVW7aRp0ZY162ySbktoW'
&& 'vxpPZULGxJLSr+G4UuX+QHrcl/rz/2eqvPgGPPWhqg0KZW5kc3RyZWFtDQplbmRvYmoNCjEwIDAgb2JqDQoyNDYNCmVuZG9iag0K'
&& 'NCAwIG9iag0KPDwNCi9UeXBlIC9QYWdlDQovUGFyZW50IDUgMCBSDQovUmVzb3VyY2VzIDw8DQovRm9udCA8PA0KL0YwIDYgMCBS'
&& 'IA0KL0YxIDcgMCBSIA0KPj4NCi9Qcm9jU2V0IDIgMCBSDQo+Pg0KL0NvbnRlbnRzIDkgMCBSDQo+Pg0KZW5kb2JqDQo2IDAgb2Jq'
&& 'DQo8PA0KL1R5cGUgL0ZvbnQNCi9TdWJ0eXBlIC9UcnVlVHlwZQ0KL05hbWUgL0YwDQovQmFzZUZvbnQgL0FyaWFsDQovRW5jb2Rp'
&& 'bmcgL1dpbkFuc2lFbmNvZGluZw0KPj4NCmVuZG9iag0KNyAwIG9iag0KPDwNCi9UeXBlIC9Gb250DQovU3VidHlwZSAvVHJ1ZVR5'
&& 'cGUNCi9OYW1lIC9GMQ0KL0Jhc2VGb250IC9Cb29rQW50aXF1YSxCb2xkDQovRmlyc3RDaGFyIDMxDQovTGFzdENoYXIgMjU1DQov'
&& 'V2lkdGhzIFsgNzUwIDI1MCAyNzggNDAyIDYwNiA1MDAgODg5IDgzMyAyMjcgMzMzIDMzMyA0NDQgNjA2IDI1MCAzMzMgMjUwIA0K'
&& 'Mjk2IDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUwMCAyNTAgMjUwIDYwNiA2MDYgNjA2IA0KNDQ0IDc0NyA3'
&& 'NzggNjY3IDcyMiA4MzMgNjExIDU1NiA4MzMgODMzIDM4OSAzODkgNzc4IDYxMSAxMDAwIDgzMyANCjgzMyA2MTEgODMzIDcyMiA2'
&& 'MTEgNjY3IDc3OCA3NzggMTAwMCA2NjcgNjY3IDY2NyAzMzMgNjA2IDMzMyA2MDYgDQo1MDAgMzMzIDUwMCA2MTEgNDQ0IDYxMSA1'
&& 'MDAgMzg5IDU1NiA2MTEgMzMzIDMzMyA2MTEgMzMzIDg4OSA2MTEgDQo1NTYgNjExIDYxMSAzODkgNDQ0IDMzMyA2MTEgNTU2IDgz'
&& 'MyA1MDAgNTU2IDUwMCAzMTAgNjA2IDMxMCA2MDYgDQo3NTAgNTAwIDc1MCAzMzMgNTAwIDUwMCAxMDAwIDUwMCA1MDAgMzMzIDEw'
&& 'MDAgNjExIDM4OSAxMDAwIDc1MCA3NTAgDQo3NTAgNzUwIDI3OCAyNzggNTAwIDUwMCA2MDYgNTAwIDEwMDAgMzMzIDk5OCA0NDQg'
&& 'Mzg5IDgzMyA3NTAgNzUwIA0KNjY3IDI1MCAyNzggNTAwIDUwMCA2MDYgNTAwIDYwNiA1MDAgMzMzIDc0NyA0MzggNTAwIDYwNiAz'
&& 'MzMgNzQ3IA0KNTAwIDQwMCA1NDkgMzYxIDM2MSAzMzMgNTc2IDY0MSAyNTAgMzMzIDM2MSA0ODggNTAwIDg4OSA4OTAgODg5IA0K'
&& 'NDQ0IDc3OCA3NzggNzc4IDc3OCA3NzggNzc4IDEwMDAgNzIyIDYxMSA2MTEgNjExIDYxMSAzODkgMzg5IDM4OSANCjM4OSA4MzMg'
&& 'ODMzIDgzMyA4MzMgODMzIDgzMyA4MzMgNjA2IDgzMyA3NzggNzc4IDc3OCA3NzggNjY3IDYxMSANCjYxMSA1MDAgNTAwIDUwMCA1'
&& 'MDAgNTAwIDUwMCA3NzggNDQ0IDUwMCA1MDAgNTAwIDUwMCAzMzMgMzMzIDMzMyANCjMzMyA1NTYgNjExIDU1NiA1NTYgNTU2IDU1'
&& 'NiA1NTYgNTQ5IDU1NiA2MTEgNjExIDYxMSA2MTEgNTU2IDYxMSANCjU1NiBdDQovRW5jb2RpbmcgL1dpbkFuc2lFbmNvZGluZw0K'
&& 'L0ZvbnREZXNjcmlwdG9yIDggMCBSDQo+Pg0KZW5kb2JqDQo4IDAgb2JqDQo8PA0KL1R5cGUgL0ZvbnREZXNjcmlwdG9yDQovRm9u'
&& 'dE5hbWUgL0Jvb2tBbnRpcXVhLEJvbGQNCi9GbGFncyAxNjQxOA0KL0ZvbnRCQm94IFsgLTI1MCAtMjYwIDEyMzYgOTMwIF0NCi9N'
&& 'aXNzaW5nV2lkdGggNzUwDQovU3RlbVYgMTQ2DQovU3RlbUggMTQ2DQovSXRhbGljQW5nbGUgMA0KL0NhcEhlaWdodCA5MzANCi9Y'
&& 'SGVpZ2h0IDY1MQ0KL0FzY2VudCA5MzANCi9EZXNjZW50IDI2MA0KL0xlYWRpbmcgMjEwDQovTWF4V2lkdGggMTAzMA0KL0F2Z1dp'
&& 'ZHRoIDQ2MA0KPj4NCmVuZG9iag0KMiAwIG9iag0KWyAvUERGIC9UZXh0ICBdDQplbmRvYmoNCjUgMCBvYmoNCjw8DQovS2lkcyBb'
&& 'NCAwIFIgXQ0KL0NvdW50IDENCi9UeXBlIC9QYWdlcw0KL01lZGlhQm94IFsgMCAwIDYxMiA3OTIgXQ0KPj4NCmVuZG9iag0KMSAw'
&& 'IG9iag0KPDwNCi9DcmVhdG9yICgxNzI1LmZtKQ0KL0NyZWF0aW9uRGF0ZSAoMS1KYW4tMyAxODoxNVBNKQ0KL1RpdGxlICgxNzI1'
&& 'LlBERikNCi9BdXRob3IgKFVua25vd24pDQovUHJvZHVjZXIgKEFjcm9iYXQgUERGV3JpdGVyIDMuMDIgZm9yIFdpbmRvd3MpDQov'
&& 'S2V5d29yZHMgKCkNCi9TdWJqZWN0ICgpDQo+Pg0KZW5kb2JqDQozIDAgb2JqDQo8PA0KL1BhZ2VzIDUgMCBSDQovVHlwZSAvQ2F0'
&& 'YWxvZw0KL0RlZmF1bHRHcmF5IDExIDAgUg0KL0RlZmF1bHRSR0IgIDEyIDAgUg0KPj4NCmVuZG9iag0KMTEgMCBvYmoNClsvQ2Fs'
&& 'R3JheQ0KPDwNCi9XaGl0ZVBvaW50IFswLjk1MDUgMSAxLjA4OTEgXQ0KL0dhbW1hIDAuMjQ2OCANCj4+DQpdDQplbmRvYmoNCjEy'
&& 'IDAgb2JqDQpbL0NhbFJHQg0KPDwNCi9XaGl0ZVBvaW50IFswLjk1MDUgMSAxLjA4OTEgXQ0KL0dhbW1hIFswLjI0NjggMC4yNDY4'
&& 'IDAuMjQ2OCBdDQovTWF0cml4IFswLjQzNjEgMC4yMjI1IDAuMDEzOSAwLjM4NTEgMC43MTY5IDAuMDk3MSAwLjE0MzEgMC4wNjA2'
&& 'IDAuNzE0MSBdDQo+Pg0KXQ0KZW5kb2JqDQp4cmVmDQowIDEzDQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwMDIxNzIgMDAwMDAg'
&& 'bg0KMDAwMDAwMjA0NiAwMDAwMCBuDQowMDAwMDAyMzYzIDAwMDAwIG4NCjAwMDAwMDAzNzUgMDAwMDAgbg0KMDAwMDAwMjA4MCAw'
&& 'MDAwMCBuDQowMDAwMDAwNTE4IDAwMDAwIG4NCjAwMDAwMDA2MzMgMDAwMDAgbg0KMDAwMDAwMTc2MCAwMDAwMCBuDQowMDAwMDAw'
&& 'MDIxIDAwMDAwIG4NCjAwMDAwMDAzNTIgMDAwMDAgbg0KMDAwMDAwMjQ2MCAwMDAwMCBuDQowMDAwMDAyNTQ4IDAwMDAwIG4NCnRy'
&& 'YWlsZXINCjw8DQovU2l6ZSAxMw0KL1Jvb3QgMyAwIFINCi9JbmZvIDEgMCBSDQovSUQgWzw0NzE0OTUxMDQzM2RkNDg4MmYwNWY4'
&& 'YzEyNDIyMzczND48NDcxNDk1MTA0MzNkZDQ4ODJmMDVmOGMxMjQyMjM3MzQ+XQ0KPj4NCnN0YXJ0eHJlZg0KMjcyNg0KJSVFT0YN'
&& 'CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
&& 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
&& 'AAAAAAAAAAAAAAAAAAAA'.
CALL TRANSFORMATION ID SOURCE x = base64_string RESULT x = result.
ENDMETHOD.
Question also discussed there.

hmac authentication in vcl

I am trying to authenticate URL using hamc. I can do the following to verify.My question is how do I parse the URL to extract only part of the URL excluding the hmac parameter. I tried using local variables in vcl but it threw an error.
Any suggestions on how to extract the hmac value and URL query parameters as shown below.
http://localhost/zzz/?q1=xxx&q2=yyy&hmac=hash
if (digest.hmac_md5("key", "q1=xxx&q2=yyy") != "value")
{
return (synth(401, digest.hmac_md5("key", "http://localhost/zzz/?q1=xxx&q2=yyy")));
}
Thanks
You'll want to use the [querystring][1] vmod. As far as I know it does not come pre-packaged, so you will need to build it but it should do exactly what you need.
With that you can define regexes/static values to match querystring arguments, and then filter those out or in.
there is no need for a external plugin in that case you can just strip out the hmac=XXX query string parameter, from req.url and store the result in a new variable req.http.url_without_hmac and req.http.hmac to the digest.hmac_md5
see a sample test case:
varnishtest "Strip query parameter"
server s1 {
rxreq
txresp
rxreq
txresp
} -start
varnish v1 -vcl+backend {
import std;
sub vcl_recv {
# Strip out HMAC parameter
# get only the query string, ignore uri
set req.http.qs = regsuball(req.url, ".*\?(.*?)$", "?\1");
# strip hmac= from the qs
set req.http.url_without_hmac = regsuball(req.http.qs,"\?hmac=[^&]+$",""); # strips when QS = "?hmac=AAA"
set req.http.url_without_hmac = regsuball(req.http.url_without_hmac,"\?hmac=[^&]+&","?"); # strips when QS = "?hmac=AAA&foo=bar"
set req.http.url_without_hmac = regsuball(req.http.url_without_hmac,"&hmac=[^&]+",""); # strips when QS = "?foo=bar&hmac=AAA" or QS = "?foo=bar&hmac=AAA&bar=baz"
# remove the leading ? from the url_without_hmac
set req.http.url_without_hmac = regsuball(req.http.url_without_hmac,"^\?(.*)$", "\1");
# extract the hmac= value from the req.http.qs
set req.http.hmac = regsuball(req.http.qs, ".*[?&]hmac=([^&]*).*", "\1");
# NOW USE req.http.url_without_hmac for your digest validation and req.http.hmac as the value
}
sub vcl_deliver {
set resp.http.url_without_hmac = req.http.url_without_hmac;
set resp.http.hmac = req.http.hmac;
}
} -start
client c1 {
txreq -url "/1?a=1&hmac=2&b=1"
rxresp
expect resp.http.url_without_hmac == "a=1&b=1"
expect resp.http.hmac == "2"
} -run
client c2 {
txreq -url "/1?hmac=hello&a=1&b=1"
rxresp
expect resp.http.url_without_hmac == "a=1&b=1"
expect resp.http.hmac == "hello"
} -run

Stringify macro values in Objective C?

I'm developing in XCode 4.2, and was wondering how I could stringify macro parameters? I was trying to use # as I thought I would do in C, but to no avail. Here is my macro:
#define ASSIGN_PROPERTY(PROP_NAME, PROP_NAME_PARAM) { \
if (PROP_NAME_PARAM == nil) { \
NSAssert(PROP_NAME != nil, #"#PROP_NAME is already nil"); \
PROP_NAME = nil; \
} else { \
NSAssert1(PROP_NAME == nil, #"#PROP_NAME is already set, address=%p", PROP_NAME); \
PROP_NAME = PROP_NAME_PARAM; \
} \
}
Then in a class that has foo as a property, I define its setter like so:
- (void) setFoo:(NSObject *)fooParam {
ASSIGN_PROPERTY(foo, fooParam)
}
Say a client calls setFoo with a non-nil value, but the foo property is already non-nil. I want the macro to print:
foo is already set, address=0x5e55400
But instead it's printing:
#PROP_NAME is already set, address=0x5e55400
Any advice?
Have you tried something like
NSAssert(PROP_NAME != nil, #"%s is already nil", #PROP_NAME);

Resources