Creating a file and writing contents into it in Dynamics Business central (AL) - azure-storage

I am trying to create a file on azure storage using Dynamics Business Central and then trying to write a string into the file. I am not able to create the file Can anyone help me in this regard.
My Sample code is
cha := 13;
msVersion := '02-14-2014';
MethodType := 'CreateFile';
keyss := 'i0PNZ6Ykse7oSSfUzFeA36rQf5wybQWh5Jol0NRM4sal4s8B3ipkjvfzcsP8';
//contenttype := 'This is sample text.';
//contentLength := StrLen(contenttype);
dateInRfc1123Format := CurrentDateTime;
//canonicalizedHeaders := 'x-ms-date:' + FORMat(dateInRfc1123Format) + Format(cha) + 'x-ms-version:02-02-2019';
requestMethod := 'PUT';
urlPath := 'lables/' + 'tre11.csv';
canonicalizedResource := '/bcstorage/labes/tre11.csv';
canonicalizedHeaders := 'x-ms-content-length:1024' + Format(cha) + 'x-ms-date:' + FORMat(dateInRfc1123Format) + Format(cha) + 'x-ms-type:file' + Format(cha) + 'x-ms-version:' + msVersion;
stringToSign := (requestMethod + Format(cha) + Format(cha) + Format(cha) + Format(cha) + Format(cha) + Format(cha) + Format(cha) + Format(cha) +
Format(cha) + Format(cha) + Format(cha) + Format(cha) + canonicalizedHeaders + canonicalizedResource);
authorizationHeader := 'SharedKey bc365storage:' + EncryptionManagement.GenerateBase64KeyedHashAsBase64String(stringToSign, keyss, 2);
Message((authorizationHeader));
request.SetRequestUri('https://bcstorage.file.core.windows.net/labes/tre11.csv');
//request.GetHeaders(RequestHeader);
request.Method := requestMethod;
RequestHeader.Add('x-ms-date', FORMat(dateInRfc1123Format));
RequestHeader.Add('x-ms-version', msVersion);
RequestHeader.Add('Authorization', authorizationHeader);
RequestHeader.Add('Accept-Charset', 'UTF-8');
//RequestHeader.Add('Content-Type', 'text/xml;charset=utf-8');
if MethodType = 'CreateFile' then begin
RequestHeader.Add('x-ms-content-length', '1024');
RequestHeader.Add('x-ms-type', 'file');
end;
client.Get('https://bcstorage.file.core.windows.net/labes/tre11.csv', hhtpres);
hhtpres.Content.ReadAs(res);
Message(res);
test := client.Send(request, hhtpres);
But i get wrong response and i am not able to create the file too.

This line
RequestHeader.Add('x-ms-date', FORMat(dateInRfc1123Format));
Formats your date based on your server's region settings, use it like this to assert proper filter all the time:
RequestHeader.Add('x-ms-date', Format(dateInRfc1123Format,0,9));
This will format your data to XML style aka YYY-MM-DD

Related

Invalid AWS Access Key when calling S3 from Apex

I am attempting to access s3 from Apex using credentials returned from AssumeRole. However, I am receiving the following error:
<Message>The AWS Access Key Id you provided does not exist in our records.</Message>
<AWSAccessKeyId>ASIA********</AWSAccessKeyId>
I am able to successfully call GetObject on this s3 bucket from the CLI using the credentials returned from AssumeRole, so I can be reasonably sure that my bucket permissions have been set up fine. I have the following code in Apex:
Http http = new http();
Profile p = [SELECT Id FROM Profile WHERE Profile.Name = 'S3 Test User' LIMIT 1];
S3_Settings__c s3 = S3_Settings__c.getInstance(p.Id);
String exp = String.valueOf(Cache.Session.get('expiration'));
String sessionToken = String.valueOf(Cache.Session.get('token'));
if(exp == null || exp == '' || (DateTime) JSON.deserialize('"' + exp + '"', DateTime.class) < System.now()) {
requestSessionToken();
}
sessionToken = String.valueOf(Cache.Session.get('token'));
DateTime expires = (DateTime) JSON.deserialize('"' + String.valueOf(Cache.Session.get('expiration')) + '"', DateTime.class);
String accessKeyId = String.valueOf(Cache.Session.get('accessKeyId'));
String accessSecret = String.valueOf(Cache.Session.get('secret'));
String bucketname = s3.Recording_Bucket__c;
String host = 's3.amazonaws.com';
String formattedDateString = Datetime.now().formatGMT('EEE, dd MMM yyyy HH:mm:ss z');
String method = 'GET';
String filePath = 'https://' + bucketname + '.' + host + '/' + filename;
HttpRequest req = new HttpRequest();
req.setMethod(method);
req.setEndpoint(filePath);
req.setHeader('Host', bucketname + '.' + host);
req.setHeader('Connection', 'keep-alive');
String stringToSign = 'GET\n\n' + 'x-amz-security-token=' + sessionToken + '&expiration=' + expires + '\n' + formattedDateString + '\n/' + '/' + bucketname + '/' + filename;
System.debug('SIGN ' + stringToSign);
String encodedStringToSign = EncodingUtil.urlEncode(stringToSign, 'UTF-8');
Blob mac = Crypto.generateMac('HMACSHA1', blob.valueof(stringToSign),blob.valueof(accessSecret));
String signedKey = EncodingUtil.base64Encode(mac);
String authHeader = 'AWS' + ' ' + accessKeyId + ':' + signedKey;
req.setHeader('Date', formattedDateString);
//req.setHeader('x-amz-security-token', sessionToken); //AWS returns 'invalid signature' if this is set
req.setHeader('Authorization',authHeader);
HttpResponse resp = http.send(req);
It seems as if the AWS is reading in the AccessKeyId/Secret, but not the session token. I've also tried setting x-amz-security-token as a header, but this throws a 403 Error -- Signature mismatch. Am I missing something within my headers or signature that would enable this request to return successfully?
Turns out I was placing the x-amz-security-token header in the wrong location. It needs to occur in the canonical AMZ Headers section immediately after the formatted date, with a comma to separate the name and value:
String stringToSign = 'GET\n\n\n' + formattedDateString + '\n' + 'x-amz-security-token:' + sessionToken + '\n' + '/' + bucketname + '/' + filename;
Additionally, the following line needed to be uncommented:
req.setHeader('x-amz-security-token', sessionToken);
As a last note, be sure that neither the header nor the canonicalized AMZ Header are capitalized.

Katalon Studio - Cannot send the test request: Invalid start or end

I'm trying to send 'POST' web request to specific address (for example: https://qa.alycedev.com/)
Any properties set (header, body, cookies, url encode/decode) leads to error while sending my web request:
Warning > Cannot send the test request. Reason:
java.lang.IllegalArgumentException: invalid start or end.
Below you can find details of error:
https://i.stack.imgur.com/szGan.png
Example of my request:
#Keyword
def purchase_simple (def totalCookies) {
WebUI.comment('Total number of cookies=' +totalCookies.size())
RequestObject ro = new RequestObject('A')
ro.setRestRequestMethod('POST')
ro.setRestUrl('https://qa.alycedev.com/gifter/dashboard')
def httpheader = new ArrayList<TestObjectProperty>()
httpheader.add(new TestObjectProperty('Content-Type', ConditionType.EQUALS, 'application/json'))
httpheader.add(new TestObjectProperty('Accept', ConditionType.EQUALS, 'application/json'))
for (Cookie currentCookie : totalCookies) {
httpheader.add(new TestObjectProperty('Cookie', ConditionType.EQUALS, 'domain='+currentCookie.getDomain() + '; '+currentCookie.getName() + '=' + currentCookie.getValue() + '; expires='+currentCookie.getExpiry() + '; Max-Age=7200; path=/;'))
}
ro.setHttpHeaderProperties(httpheader)
def body = '{"_token": "' + GlobalVariable.G_api_oauth.csrfToken + '","use_credits": ' + GlobalVariable.G_product.price + ',"use_payment": 0.00,"currency_id": 1,"total_price": ' + GlobalVariable.G_product.price + ',"payment_data" : null,"gift_send_data": "{"id":' + GlobalVariable.G_gift.id + ',"product_id":' + GlobalVariable.G_product.id + ',"total_price":' + GlobalVariable.G_product.price + ',"send_now":true,"schedule_at":"","send_type":"hwcard","gifter_company":"Apple","giftee_company":"Sony","from":null,"gifter_address":{"country":{"id":1,"name":"United States","code":"US","image":""},"country_id":1,"address":"Address","address2":"Address 2","city":"City","state":"State","zipcode":"123321"},"giftee_address":{"country":{"id":1,"name":"United States","code":"US","image":""},"country_id":1,"address":"Address","address2":"Address 2","city":"City","state":"State","zipcode":"123321"},"message_to_giftee":{"id":1,"default":1,"message":"Messages subject + 10 characters.","subject":"Something for your time","name":"Something for your time"},"prospect":{"capture_date":true,"capture_email":true,"capture_phone":true,"capture_question":false,"capture_affidavit":false,"gifter_affidavit":"","gifter_question":""},"delivery_method_data":{"type":"branded_box"}}"}'
ro.setBodyContent(new HttpTextBodyContent(body, 'UTF-8', 'application/json'))
WebUI.comment(ro.activeProperties.toArray().toString())
try{
def response = WSBuiltInKeywords.sendRequest(ro)
}
catch(Exception ex) {
println(ex.detailMessage)
println(ex.stackTraceDepth.toString())
}
}

IBM MobileFirst -- get location

I have MobileFirst (V7.O) app . How do I get the current latitude/Longitude for the device. Basically, I am recording some information at various point in my app and user can be moving.. So, at various instance, I would like to get the current lat/log..
Can you please provide some hints and how to get this information
Thanks for your help
Cordova is bundled in your MobileFirst project. As such you can take use of Cordova APIs to achieve this.
See the following (scroll down to the API usage): https://github.com/apache/cordova-plugin-geolocation
// onSuccess Callback
// This method accepts a Position object, which contains the
// current GPS coordinates
//
var onSuccess = function(position) {
alert('Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
};
// onError Callback receives a PositionError object
//
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);

How to make store to get data using stored procedure

I have file XML here:
<Setup>
<Include Type="Product">
<Value uomid="8078">469700_3:9000;2:10000;</Value>
</Include>
</Setup>
And this is my store to get data:
PromotionSetup.query(''
for $PS in Setup/Include[#Type = ''''Product'''']/Value[text()]
where contains($PS, ''''' + CAST(#productID AS NVARCHAR) + '_'''') or $PS = ''''' + CAST(#productID AS NVARCHAR) + '''''
return data($PS)
'')).value(''(.)'', ''nvarchar(max)'') as InfoProductPromotion
This store just receive one parameter, that mean is: 469700.
So. I got an ordeal that set two parameter: one is ProductID: 469700 and the second is: uomid : 8078. And the result will be 469700_3:9000;2:10000;.
So can someone help me to make a store procedure to get data with 2 parameters.
My problem is sovled:
PromotionSetup.query(''
for $PS in Setup/Include[#Type = ''''Product'''']/Value[#uomid='''''+CAST(#uomID as nvarchar)+'''''][text()]
where contains($PS, ''''' + CAST(#productID AS NVARCHAR) + '_'''') or $PS = ''''' + CAST(#productID AS NVARCHAR) + '''''
return data($PS)'')).value(''(.)'', ''nvarchar(max)'') as InfoProductPromotion

How to Retrieve all possible information about a LinkedIn Account ? (API using C#)

I am writting an C# app to make use of Linkedin's API.
I want to be able to query "Person" (First Name + Last Name) and retrieve all the possible information about this group of people with the same name
I am currently using my own implementation of the REST API alongside People-Search API calls.
Here's an example of a request that I know works:
https://api.linkedin.com/v1/people-search:(people:(id,first-name,last-name,headline,picture-url),num-results)?
I'm running it with: first-name=parameter&last-name=parameter after the ? mark
The problem is, I want to retrieve more information such as Title, Industry, Current-company, current-school etc. Refer here for the list of possible parameters.
This notation is what they call Field Selectors
How do i structure my API Call so i can get all the possible information about someone ?
Here is the url to get everything for a user Profile:
https://api.linkedin.com/v1/people/~:(id,first-name,last-name,headline,picture-url,industry,summary,specialties,positions:(id,title,summary,start-date,end-date,is-current,company:(id,name,type,size,industry,ticker)),educations:(id,school-name,field-of-study,start-date,end-date,degree,activities,notes),associations,interests,num-recommenders,date-of-birth,publications:(id,title,publisher:(name),authors:(id,name),date,url,summary),patents:(id,title,summary,number,status:(id,name),office:(name),inventors:(id,name),date,url),languages:(id,language:(name),proficiency:(level,name)),skills:(id,skill:(name)),certifications:(id,name,authority:(name),number,start-date,end-date),courses:(id,name,number),recommendations-received:(id,recommendation-type,recommendation-text,recommender),honors-awards,three-current-positions,three-past-positions,volunteer)?oauth2_access_token=PUT_YOUR_TOKEN_HERE
Requires an Oauth2 access token.
Here it is in a nice String list (Java):
apiUrl
+ "/v1/people/~:("
+ "id,"
+ "first-name,"
+ "last-name,"
+ "headline,"
+ "picture-url,"
+ "industry,"
+ "summary,"
+ "specialties,"
+ "positions:("
+ "id,"
+ "title,"
+ "summary,"
+ "start-date,"
+ "end-date,"
+ "is-current,"
+ "company:("
+ "id,"
+ "name,"
+ "type,"
+ "size,"
+ "industry,"
+ "ticker)"
+"),"
+ "educations:("
+ "id,"
+ "school-name,"
+ "field-of-study,"
+ "start-date,"
+ "end-date,"
+ "degree,"
+ "activities,"
+ "notes),"
+ "associations," /* Full Profile */
+ "interests,"
+ "num-recommenders,"
+ "date-of-birth,"
+ "publications:("
+ "id,"
+ "title,"
+ "publisher:(name),"
+ "authors:(id,name),"
+ "date,"
+ "url,"
+ "summary),"
+ "patents:("
+ "id,"
+ "title,"
+ "summary,"
+ "number,"
+ "status:(id,name),"
+ "office:(name),"
+ "inventors:(id,name),"
+ "date,"
+ "url),"
+ "languages:("
+ "id,"
+ "language:(name),"
+ "proficiency:(level,name)),"
+ "skills:("
+ "id,"
+ "skill:(name)),"
+ "certifications:("
+ "id,"
+ "name,"
+ "authority:(name),"
+ "number,"
+ "start-date,"
+ "end-date),"
+ "courses:("
+ "id,"
+ "name,"
+ "number),"
+ "recommendations-received:("
+ "id,"
+ "recommendation-type,"
+ "recommendation-text,"
+ "recommender),"
+ "honors-awards,"
+ "three-current-positions,"
+ "three-past-positions,"
+ "volunteer"
+ ")"
+ "?oauth2_access_token="+ token;
You've already got the notation down, all you need to do is add the rest of the field selectors, nesting them where needed:
https://api.linkedin.com/v1/people-search:(people:(id,first-name,last-name,headline,picture-url,industry,positions:(id,title,summary,start-date,end-date,is-current,company:(id,name,type,size,industry,ticker)),educations:(id,school-name,field-of-study,start-date,end-date,degree,activities,notes)),num-results)?first-name=parameter&last-name=parameter
Keep in mind that per the Profile Field docs, you can only get educations for 1st degree connections of the current user.
I use this URL to get everything including email and formatted as json:
https://api.linkedin.com/v1/people/~:(id,first-name,email-address,last-name,headline,picture-url,industry,summary,specialties,positions:(id,title,summary,start-date,end-date,is-current,company:(id,name,type,size,industry,ticker)),educations:(id,school-name,field-of-study,start-date,end-date,degree,activities,notes),associations,interests,num-recommenders,date-of-birth,publications:(id,title,publisher:(name),authors:(id,name),date,url,summary),patents:(id,title,summary,number,status:(id,name),office:(name),inventors:(id,name),date,url),languages:(id,language:(name),proficiency:(level,name)),skills:(id,skill:(name)),certifications:(id,name,authority:(name),number,start-date,end-date),courses:(id,name,number),recommendations-received:(id,recommendation-type,recommendation-text,recommender),honors-awards,three-current-positions,three-past-positions,volunteer)?format=json