We are using MS Graph api to collect Ad user information. One of our method suddenly stop working when using our groovy script.
Actually when calling the Graph API url from POSTMAN directly for requesting user information we receive the following response
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
"value": [
{
"businessPhones": [],
"displayName": "Rhea Sam",
"givenName": null,
"jobTitle": null,
"mail": "user#mydoamin.com",
"mobilePhone": null,
"officeLocation": null,
"preferredLanguage": null,
"surname": null,
"userPrincipalName": "user#mydoamin.com#EXT##rlxcom.onmicrosoft.com",
"id": "05906321-ed38-4bfd-9c9e-02bfb7d32405"
}
]
}
Until now our groovy script call for that same API was working well but then suddenly stop working
Here is calling method code we are using
public String getGuestUserId(String AuthToken,String userEmail){
String _userId
def http = new HTTPBuilder("https://graph.microsoft.com/v1.0/users/?")
http.request(GET) {
requestContentType = ContentType.JSON
//uri.query = [ $filter:"mail eq '$userEmail'"].toString()
uri.query=[$filter:"mail eq '$userEmail'"]
headers.'Authorization' = "Bearer " + AuthToken
response.success = { resp, json ->
if (**json.value**){
_userId=**json.value**[0].id
}
else
_userId=-1 // user does not exist
}
// user ID not found : error 404
response.'404' = { resp ->
_userId = 'Not Found'
}
}
_userId
}
What is happening when executing this method now is that the json.value return an error saying :
"No such property: value for class: java.lang.Object"
Note that if we try to return just the json.toString() then it return only
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
"value": []
What is wrong and how to solve it as it is suppose to return same information as the POSTMAN response in which we are concerned only to retrive the Id of teh user from the response
Thanks for your help
regards
Related
I am copying a file from one drive to another. As part of the body request, I am also providing conflictBehavior as rename (tried with replace as well) but the copy is failing.
POST: https://graph.microsoft.com/beta/users/{user-id}/drive/items/{item-id}/copy
Body:
{
"parentReference": {"id": {folder-id-to-copy}, "driveId": {drive-id},
"#microsoft.graph.conflictBehavior": "rename"
}
After executing above command, as expected I get a 202 and in the header I look at Location. When querying the monitor URL, I see the below error:
{
"#odata.context": "https://{host-name}/_api/v2.1/$metadata#drives('default')/operations/$entity",
"id": "7a0decd4-df2f-4717-8eee-b7c2cd131009",
"createdDateTime": "0001-01-01T00:00:00Z",
"lastActionDateTime": "0001-01-01T00:00:00Z",
"status": "failed",
"error": {
"code": "nameAlreadyExists",
"message": "Name already exists"
}
}
What to pass in order to rename/replace existing file while copying
If you are trying to rename it with special name, then try this.
POST /users/{user-id}/drive/items/{item-id}/copy
Content-Type: application/json
{
"parentReference": {
"id": {folder-id-to-copy}, "driveId": {drive-id},
},
"name": "your_file_name (copy).txt"
}
Reference here: https://learn.microsoft.com/en-us/graph/api/driveitem-copy?...
And if you want to rename the file automatically, then try this using Instance Attributes.
POST /users/{user-id}/drive/items/{item-id}/copy?#microsoft.graph.conflictBehavior=rename
Content-Type: application/json
{
"name": "{filename}"
}
name should be provided.
if you are using GraphServiceClient, you can do the following:
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var parentReference = new ItemReference
{
DriveId = "6F7D00BF-FC4D-4E62-9769-6AEA81F3A21B",
Id = "DCD0D3AD-8989-4F23-A5A2-2C086050513F"
};
// To resolve the issue: Code: nameAlreadyExists Message: The specified item name already exists. Copy
List<QueryOption> options = new List<QueryOption>
{
new QueryOption("#microsoft.graph.conflictBehavior", "rename")
};
var name = "contoso plan (copy).txt";
await graphClient.Me.Drive.Items["{driveItem-id}"]
.Copy(name,parentReference)
.Request(options)
.PostAsync();
Ref https://learn.microsoft.com/en-us/graph/api/driveitem-copy?view=graph-rest-1.0&tabs=csharp
I'm writing test script in katalon studio to verify response body of the API.My response body is of format:
{
"status": "Success",
"correlationCode": "1234-5678",
"type": {
"id": 51247,
"name": "Student",
},
"data": {
"name": "Sara Nieves",
"gender": "Female",
"dob": "1995-08-06",
"libraryCard": {
"id": "11178",
"type": "Seniors"
},
"qualifications": [
{
"id": "45650986546",
"name": "Graduate Certificate in Environmental Engineering Management"
}
]
}
}
I want to verify that none of the elements return 'null' value. Since, the elements returned for the API response are not static(meaning name, gender etc might not get returned every time) therefore, i can't use something like "data.name" to verify if it has null value. So, i want a generic way to loop through each and every attribute returned and check if its value is returned as null or not.
Any help will be much appreciated. Thanks!
You have the error message:
groovy.lang.MissingMethodException: No signature of method: WSVerification1569811424284$_run_closure1.doCall() is applicable for argument types: (com.kms.katalon.core.testobject.ResponseObject) values: [200 1 KB] 22572.groovy:21)
I assume your response object type: com.kms.katalon.core.testobject.ResponseObject
The code to parse response as json and validate it:
import groovy.json.JsonSlurper
/**
* the recursive method to validate that json object does not have null values
* #param obj - the parsed json object (sequence of maps and lists)
* #param path - a variable to know where the error occurred in json data.
*/
void assertNoNullValue(Object obj, String path='ROOT'){
//the main assertion
assert obj!=null : "value in json could not be null: $path"
if(obj instanceof Map){
//iterate each key-value in map and validate the value recursively
obj.each{k,v-> assertNoNullValue(v,path+".$k") }
} else if(obj instanceof List){
//iterate each value in list and validate the value recursively
obj.eachWithIndex{v,i-> assertNoNullValue(v,path+"[$i]") }
}
}
def response = ...
assert response.isJsonContentType()
def responseText = response.getResponseText()
//parse body
def data = new JsonSlurper().parseText(responseText)
assertNoNullValue(data)
This solution is not as precise as the one suggested by #dagget, but it is a quick check:
def response = '''
{
"status": "Success",
"correlationCode": "1234-5678",
"type": {
"id": 51247,
"name": "Student",
},
"data": {
"name": "Sara Nieves",
"gender": "femmina",
"dob": "1995-08-06",
"libraryCard": {
"id": "11178",
"type": "Seniors"
},
"qualifications": [
{
"id": "45650986546",
"name": "Graduate Certificate in Environmental Engineering Management"
}
]
}
}
'''
assert !response.contains("null")
I have an action in IBM Cloud Functions that only receives one parameter: "frame". I'm using Postman to test the REST API endpoint provided with the action. However, when I provide the "frame" parameter it returns the following:
"response": {
"result": {
"error": "'frame'"
},
"status": "application error",
"success": false
}
I've experienced this problem when I invoke this action in the IBM Cloud Functions' console. I resolve it by erasing a space in the input modal and adding it again, then it works like a charm in the console. However, I can't do the same thing with an HTTP request.
The way I'm currently doing the HTTP request is like this:
POST https://us-south.functions.cloud.ibm.com/api/v1/namespaces/{namespace}/actions/{action_name}?blocking=true&frame={value}
The action should return the result I'm expecting but it doesn't do that right now. Please help me, any answers would be great!
EDIT:
This is the action's code:
import requests, base64, json, cv2
from PIL import Image
from six import BytesIO
def json_to_dict(json_str):
return json.loads(json.dumps(json_str))
def frame_to_bytes(frame):
frame_im = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
pil_im = Image.fromarray(frame_im)
stream = BytesIO()
pil_im.save(stream, format="JPEG")
stream.seek(0)
img_for_post = stream.read()
img_base64 = base64.b64encode(img_for_post)
return img_base64
def main(dict):
cap = cv2.VideoCapture(dict['frame'])
if not cap.isOpened():
return { "error": "Unable to open video source" }
ret, frame = cap.read()
if ret is False:
return { "error": "Unable to read video source" }
# openALPR API part
OPENALPR_SECRET_KEY = {my_secret_key}
url = "https://api.openalpr.com/v2/recognize_bytes?recognize_vehicle=1&country=us&secret_key=%s" % (
OPENALPR_SECRET_KEY)
r = requests.post(url, data=frame_to_bytes(frame))
resp = json_to_dict(r.json())
print(resp)
if not resp['results']:
return { "error": "Plate number not recognized" }
plates = []
for plate in resp['results']:
if plate['confidence'] < 75:
pass
else:
print(plate['plate'])
plates.append(plate['plate'])
return { "plates": plates }
This is the activation response (the status returned was 502 Bad Gateway according to Postman):
{
"activationId": "5a83396b9f53447483396b9f53e47452",
"annotations": [
{
"key": "path",
"value": "{namespace}/{name}"
},
{
"key": "waitTime",
"value": 5531
},
{
"key": "kind",
"value": "python:3.7"
},
{
"key": "timeout",
"value": false
},
{
"key": "limits",
"value": {
"concurrency": 1,
"logs": 10,
"memory": 1024,
"timeout": 60000
}
},
{
"key": "initTime",
"value": 3226
}
],
"duration": 3596,
"end": 1560669652454,
"logs": [],
"name": "{name}",
"namespace": "{namesapce}",
"publish": false,
"response": {
"result": {
"error": "'frame'"
},
"status": "application error",
"success": false
},
"start": 1560669648858,
"subject": "{my_email}",
"version": "0.0.7"
}
EDIT 2:
I've also tried to enable it as a web action to see if it changes anything. However, it's no use. When I use this HTTP request:
https://us-south.functions.cloud.ibm.com/api/v1/web/{namespace}/default/{action_name}?frame={value}
I get:
{
"code": "e1c36666f4db1884c48f028ef58243fc",
"error": "Response is not valid 'message/http'."
}
which is understandable since what my functions returns is json. However, when I use this HTTP request:
https://us-south.functions.cloud.ibm.com/api/v1/web/{namespace}/default/{action_name}.json?frame={value}
I get:
{
"code": "010fc0efaa29f96b47f92735ff763f50",
"error": "Response is not valid 'application/json'."
}
I really don't know what to do here
After googling a bit I found something that works for me right now although it might not work for everyone. Apache has a python "client" example for using an action's REST API which uses the requests library.
Thing is that in order to use it you need to provide your API KEY, which I don't know how to get by any other means than getting it directly from the IBM Cloud CLI. Since I'm trying to access the function from a web server, I would need to save the key in an environment variable or save it in a text file and access it from there or install the CLI on the server, login with my credentials and call ibmcloud wsk property get --auth.
Also, this method didn't work with the web action endpoint when I tried it.
I am trying to create a checkout via Shopify admin rest API and in response, I am getting a validation error which looks like this.
{
"errors": {
"line_items": {
"0": {
"variant_id": [
{
"code": "invalid",
"message": "is invalid",
"options": {}
}
]
}
}
}
}
Request[POST]:
URL: https://mystore.myshopify.com/admin/checkouts.json
{
"checkout": {
"line_items": [
{
"variant_id": "15465470460017",
"quantity": 1
}
]
}
}
I verified the varient_id by looking into the cart JSON on the link "https://mystore.myshopify.com/cart.json".
I also followed the documentation given on Shopify. If I create empty checkout without varient_id then it works otherwise it returns the invalid variant id error.
I tried this request on PostMan. For updated and others it is working fine but for checkout create I couldn't find the point where I am going wrong.
I'm testing Azure Schema Extensions with a simple groovy script to the Microsoft Graph API. I first query for a list of schema extensions and this seems to work (though I am not sure where the extensions in the response have been set, I assume they are there by default). I then try to POST a schema extension but this fails with this error message:
[error: [
code:InternalServerError,
message:Object reference not set to an instance of an object.,
innerError:[request-id:xxxxx-xxxx-xxx-xxxxxx, date:2018-05-14T00:46:00]]]
This is the code for the GET query and the response:
def uriTestGET = "https://graph.microsoft.com/v1.0/schemaExtensions?"
def httpTestGET = new HTTPBuilder(uriTestGET)
httpTestGET.ignoreSSLIssues()
httpTestGET.request(GET,JSON) { req ->
httpTestGET.parser.'application/json'
headers.'Authorization' = 'Bearer ' + AzureToken
headers.'Content-Type' = 'application/json'
response.failure = { resp, json ->
println "GET Failure. GROUP: ${resp.statusLine}"
println(json)
}
response.success = { resp, json ->
println "GET Success. GROUP: ${resp.statusLine}"
println(json)
}
}
Response
[
#odata.context:https://graph.microsoft.com/v1.0/$metadata#schemaExtensions,
#odata.nextLink:https://graph.microsoft.com/v1.0/schemaExtensions?$skiptoken=XXXXXXXXXX,
value:[[
id:adatumisv_exo2,
description:sample desccription,
targetTypes:[Message],
status:Available,
owner:xxxxxx-xxxx-xxxx-xxxx,
properties:[
[name:p1, type:String],
[name:p2, type:String]]],
[id:circuitid_globals,
description:Circuit ID Graph Global Schema,
targetTypes:[Group, User], .. etc
And the following POST request:
def uriTestPOST = "https://graph.microsoft.com/v1.0/schemaExtensions?"
def httpTestPOST = new HTTPBuilder(uriTestPOST)
httpTestPOST.ignoreSSLIssues()
httpTestPOST.request(POST,JSON) { req ->
httpTestPOST.parser.'application/json'
headers.'Authorization' = 'Bearer ' + AzureToken
headers.'Content-Type' = 'application/json'
body = [
"id":"TestExtension",
"description": "Test to add user object schema extension",
"status": "Available",
"targetTypes": ["user"]
]
response.failure = { resp, json ->
println "POST Failure. GROUP: ${resp.statusLine}"
println(json)
}
response.success = { resp, json ->
println "POST Success. GROUP: ${resp.statusLine}"
println(json)
}
}
This gets the response:
[error:[
code:InternalServerError,
message:Object reference not set to an instance of an object.,
innerError:[request-id:xxxx-xxxx-xxxx-xxxx, date:2018-05-14T00:46:00]]]
Updated Body looks like this -
body = [
"id":"TestExtension",
"description": "Test to add user object schema extension",
// "status": "Available",
"targetTypes": ["User"],
"properties" : [["name": "ExtensionProperty", "type":"String"]]
]
And this is the new error message:
[error:[
code:Authorization_RequestDenied,
message:Insufficient privileges to complete the operation.,
innerError:[request-id:xxxx-xxxx-xxxx-xxxx, date:2018-05-14T05:09:41]]]
I've decoded the token and it shows the following roles are included:
Decoding the token it states the following roles:
"roles": [
"User.ReadWrite.All",
"Directory.ReadWrite.All",
"User.Invite.All" ]
I've been adding additional permissions to get this to work, these seem to be greater privileges than is required as far as I can see.
The system automatically chooses between using Application or Delegated permissions based on the OAuth Grant you've chosen:
Client Credentials Grant = Application
Authorization Code Grant = Delegated
Implicit Grant = Delegated
This is because you need an actual User to authenticate if you want them to delegate your application to act on their behalf. Without a User authenticated there isn't anyone to delegate permissions so you need to operate under Application scopes.