I'm using the GetAPIProduct policy (see http://apigee.com/docs/gateway-services/content/retrieve-api-product-settings-using-getapiproduct
) to get a list of scopes. Then in a JavaScript callout, I try to reference that list of scopes, but instead of text I get back something like this (the hex chunk at the end changes with each call):
[Ljava.lang.String;#19baa7ed
There doesn't seem to be anything I can do to turn it into an array I can access using Javascript. I'm in a Free org so Java is not an option. I've tried String(), myvar.toString() and even the Rhino context.javaToJs which doesn't seem to exist in Apigee.
Any ideas how I can either convert this to a string?
It turns out that the value of getapiproduct.{policyname}.apiproduct.scopes is a zero-based array of objects. Each of those objects, though, can be converted to a string that is a scope name.
So here's how you access the array of scopes:
var scopeArray=context.getVariable("getapiproduct.RetrieveProductInfo.apiproduct.scopes");
// you can use either of these methods to convert the array elements
var firstElement = String(scopeArray[0]);
var secondElement = scopeArray[1]+'';
var scopeArrayLen = scopeArray.length;
This isn't an answer to the question, but is some additional information that may be valuable.
The GetAPIPRoductInfo gets the list of scopes on a product. Conversely, the GetOAuthV2Info policy gets information about an OAUthV2 token. Assuming you have a token you could do something like this:
<GetOAuthV2Info name='GetOAuthV2Info-TokenScopes'>
<!-- use one of the following: a referenced variable or -->
<!-- an explicitly passed access_token -->
<AccessToken ref='access_token'/>
<!--
On Success, the following flow variables will be set.
oauthv2accesstoken.{policy_name}.access_token
oauthv2accesstoken.{policy_name}.scope
oauthv2accesstoken.{policy_name}.refresh_token
oauthv2accesstoken.{policy_name}.accesstoken.{custom_attribute_name}
oauthv2accesstoken.{policy_name}.developer.id
oauthv2accesstoken.{policy_name}.developer.app.name
oauthv2accesstoken.{policy_name}.expires_in
oauthv2accesstoken.{policy_name}.status
-->
</GetOAuthV2Info>
Then you can use that information in a subsequent JS callout to check the scopes for the token against whatever requirement you have:
// checkScope.js
// ------------------------------------------------------------------
var varname = 'oauthv2accesstoken.GetOAuthV2Info-TokenScopes.scope',
approvedScopes = context.getVariable(varname),
check = false;
approvedScopes = approvedScopes.split(' ');
// approvedScopes is now a JavaScript array of strings, that lists
// the scopes the user approved for the requesting client (app).
//
// You can now compare that list against the scopes required
// for an operation or resource, and then set a variable
// determining whether the token is good for the request.
context.setVariable('scopeCheck.ok', check);
Related
I'm currently working on an application built in Scala with Spray routing.
So for dealing with a JSON document sent over POST, it's pretty easy to access the variables within the body, as follows;
respondWithMediaType(`application/json`) {
entity(as[String]) { body =>
val msg = (parse(body) \ "msg").extract[String]
val url = (parse(body) \ "url").extractOpt[String]
However, I'm now trying to write an additional query with GET, and am having some issues accessing the parameters sent through with the query.
So, I'm opening with;
get {
respondWithMediaType(`application/json`) {
parameterSeq { params =>
var paramsList = params.toList
So, this works well enough in that I can access the GET params in a sequential order (just by accessing the index) - the problem is, unfortunately I don't think we can expect GET params to always be sent in the correct order.
The list itself prints out in the following format;
List((msg,this is a link to google), (url,http://google.com), (userid,13))
Is there any simple way to access these params? For example, something along the lines of;
var message = paramsList['msg']
println(message) //returns "this is a link to google"
Or am I going about this completely wrong?
Apologies if this is a stupid question - I've only switched over to Scala very recently, and am still getting both acquainted with that, and re-acquainted with Java.
What I usually do is use the parameters directive to parse the data out to a case class which contains all the relevant data:
case class MyParams(msg: String, url: String, userId: Int)
parameters(
"msg".as[String],
"url".as[String],
"userId".as[Int]
).as[MyParams] {
myParams =>
// Here you have the case class containing all the data, already parsed.
}
To build your routes you could use the parameters directives. I'm not sure if this is what you're looking for, anyway you could use them as:
get {
parameters('msg) { (msg) =>
complete(s"The message is '$msg'")
}
}
Spray directives can be easily composed so you can use combine them in any way you want.
I hope that helps you.
I am trying to add a function to a JSONJavaObject and calling it from a control on an xpage.
so far I have:
json = (JsonJavaObject) JsonParser.fromJson(factory, colJson);
String func = "function () { alert('you clicked?'); }";
json.put("onClick", new JsonReference(func) );
In the first line I add key-value pairs from a column in a Notes view.
In the second line I define the function as a string.
In the last line I place the converted string as function in the jsonjava object.
I read about this in the following blog post:
http://camerongregor.com/2016/01/19/doublequoteavoidance/
In the next step I bind the function to e.g. a button control as followed:
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[obj.onClick]]></xp:this.script>
</xp:eventHandler>
</xp:button>
obj is the respresentation of the JSONJava object in SSJS.
But without success. Anyone know how I can call the function in the object?
I hope I will make sense here, let me know if anything to clarify.
If you are simply trying to dynamically output the client side script of a button event, then you don't need to use JsonReference at all. You can just use a String.
In my blog article I might not have make it clear why I needed to use JsonReference. I was using it in the process of rendering a custom UIComponent, part of this process required generating a Json object client side. To do this I created the JsonJavaObject as you did and then asked it to be turned into a string with the 'toJson' method. My problem was that when I asked the whole object to become a string, every property of that object that was a String, would begin and end with a double quote. I needed to ensure that the properties which were intended to be functions did not begin and end with "". By using the JsonReference the JsonGenerator became aware of my intention not to include these double quotes.
In your case, it looks as though you are just trying to dynamically determine what happens with onClick. To do this you could simply use a String instead of the JsonReference. The inclusion of the 'function() {}' is unnecessary as this will be generated when the event handler is rendered at the end of the page.
For Example here would be the Json Java Object
JsonJavaObject obj = new JsonJavaObject();
String func = " alert('you clicked?'); ";
obj.put("onClick", func);
return obj;
And here would be the button:
<xp:button id="button1" value="Alert Me">
<xp:eventHandler event="onclick" submit="false"
script="#{javascript: myBean.myObject.get('onClick')}">
</xp:eventHandler>
</xp:button>
This should give you the end result of seeing 'you clicked?' alert.
You can also inspect how this has all been generated in the script block near the end of the page using 'view Source' or your favourite web browser developer tools:
function view__id1__id2_clientSide_onclick(thisEvent) {
alert('you clicked?');
}
XSP.addOnLoad(function() {
XSP.attachEvent("view:_id1:_id2", "view:_id1:button1", "onclick",
view__id1__id2_clientSide_onclick, false, 2);
});
Let me know if anything isn't clear, hope it helps!
Does obj.onClick already give you a handle to the function returned by the Java class? If it does then you should be able to call it using the call or apply methods that are available in JavaScript:
obj.onClick.call();
obj.onClick.apply();
More details about those two methods can be found here: What is the difference between call and apply?
I'm working with jQuery DataTables. I have it listing out a view and have checkboxes to select multiple documents. I'm able to get the selected keys into session scope via this client side JavaScript code :
<xp:this.script><![CDATA[// Build array of selected rows
var myTableApi = x$("inventoryTable").DataTable();
var count = myTableApi.rows( { selected: true } ).count();
var dataArr = [];
var rowData = myTableApi.rows( { selected: true } ).data();
$.each($(rowData),function(key,value){
dataArr.push(value[3]);
});
// Push that to the requestScope
setScopeValue("session", "rowCount", count);
setScopeValue("session", "rowIds", dataArr);]]></xp:this.script>
Once the id's are in Scope I change pages and then I want to load them into my Java pageController.
I can easily use a variable resolver to get ahold of "rowIds". But I'm not sure how to get it into Java so I could work with it. Ideally I'd like it to be List or Set or something similar.
In Java, how can I convert this JavaScript Array to a Collection based object?
Thanks!
There are a few tricks to do here.
First, since the particular implementation of your setScopeValue function converts all values to a string before sending them to the server, it's important to do setScopeValue("session", "rowIds", XSP.toJson(dataArr)). That way, the value stored on the server will be ["foo", "bar", "baz"] instead of foobarbaz.
Secondly, the best way to get to the session-scoped value in Java would be via ExtLibUtil.getSessionScope().get("rowIds").
That value will be a string, though, and not an array type, so it'll have to be parsed from JSON. Using the IBM Commons JSON capabilities, that can be done with:
List<?> rowIds = (List<?>)JsonParser.fromJson(JsonJavaFactory.instance, ExtLibUtil.getSessionScope().get("rowIds"))
for(Object rowIdObj : rowIds) {
String rowId = StringUtil.toString(rowIdObj);
// do stuff with each ID here
}
You can also potentially case it directly to a List<String>, since Java's generics are really just hints for compiler-generated code, and not really enforced in the objects themselves, but there you run the risk of a ClassCastException if the incoming List contains any non-string types.
I am writing an Assertion Generator Plugin in Java to fetch a user details from Session Store and modify the values in Assertion(SAML 2.0) accordingly.
I am able to identify the method(Link) using which I can pull the user values from Session Store (agentAPIObject.getSessionVariables()) based on SessionID, but, I am having trouble writing a code to fetch specific parameters from the session store. (speficially around setting values for Attribute method and making it as an array)
Can someone post a sample code if you have ever seen/written around it, so that I can fetch user attributes from Session Store.
I am having trouble understanding Java docs around it.
Thanks in advance,
The API mentions this:
responseAttributeList - On successful return from this method (YES is
returned), this output parameter contains the retrieved variable names
and their values. If the method returns UNRESOLVED, this parameter
includes variables that could not be retrieved.
You'll need to create two AttributeList Objects. If the response of getSessionVariables(...) is YES, then the variable responseAttributeList will contain the session variables. Since Java uses references, that same variable responseAttributeList will be updated. You can then use getAttributeAt(...) to access the Attribute Objects.
String sessionID = "sampleID";
ResourceContextDef rcd = //whatever it needs to be equal to
AttributeList requestAttributeList = new AttributeList();
AttributeList responseAttributeList = new AttributeList();
if(getSessionVariables(sessionId, rcd, requestAttributeList, responseAttributeList) == YES){
Attribute att = responseAttributeList.getAttributeAt(0);//or whatever index.
}
Remember to carefully read the API.
NOTE: This is just pseudo code. I have not tested this. However, this should be plenty enough to get you going where you need to.
I'm attempting to execute an Upsert using the Novell JLDAP library, unfortunately, I'm having trouble finding an example of this. Currently, I have to:
public EObject put(EObject eObject){
Subject s = (Subject) eObject;
//Query and grab attributes from subject
LDAPAttributes attr = resultsToAttributes(getLDAPConnection().get(s));
//No modification needed - return
if(s.getAttributes().equals(attr)){
return eObject;
} else {
//Keys:
//REPLACE,ADD,DELETE, depending on which attributes are present in the maps, I choose the operation which will be used
Map<String,LDAPAttribute> operationalMap = figureOutWhichAttributesArePresent(c.getAttributes(),attr);
//Add the Modifcations to a modification array
ArrayList<LDAPModification> modList = new ArrayList<LDAPModification>();
for(Entry entry: operationalMap.getEntrySet()){
//Specify whether it is an update, delete, or insert here. (entry.getKey());
modList.add(new LDAPModification(entry.getKey(),entry.getValue());
}
//commit
connection.modify("directorypathhere",modList.toArray(new LDAPModification[modList.size()]));
}
I'd prefer to not have to query on the customer first, which results in cycling through the subject's attributes as well. Is anyone aware if JNDI or another library is able to execute an update/insert without running multiple statements against LDAP?
Petesh was correct - the abstraction was implemented within the Novell library (as well as the UnboundId library). I was able to "upsert" values using the Modify.REPLACE param for every attribute that came in, passing in null for empty values. This effectively created, updated, and deleted the attributes without having to parse them first.
In LDAP, via LDIF files, an upset would be a single event with two steps. A remove and add of a value. This is denoted by a single dash on a line, between the remove then the add.
I am not sure how you would do it in this library. I would would try to modList.remove and then modList.add one after another and see if that works.