Cloud Code: Creating a Parse.File from URL - parse-platform

I'm working on a Cloud Code function that uses facebook graph API to retrieve users profile picture. So I have access to the proper picture URL but I'm not being able to acreate a Parse.File from this URL.
This is pretty much what I'm trying:
Parse.Cloud.httpRequest({
url: httpResponse.data["attending"]["data"][key]["picture"]["data"]["url"],
success: function(httpImgFile)
{
var imgFile = new Parse.File("file", httpImgFile);
fbPerson.set("profilePicture", imgFile);
},
error: function(httpResponse)
{
console.log("unsuccessful http request");
}
});
And its returning the following:
Result: TypeError: Cannot create a Parse.File with that data.
at new e (Parse.js:13:25175)
at Object.Parse.Cloud.httpRequest.success (main.js:57:26)
at Object.<anonymous> (<anonymous>:842:19)
Ideas?

I was having trouble with this exact same problem right now. For some reason this question is already top on Google results for parsefile from httprequest buffer!
The Parse.File documentation says
The data for the file, as 1. an Array of byte value Numbers, or 2. an Object like { base64: "..." } with a base64-encoded String. 3. a File object selected with a file upload control. (3) only works in Firefox 3.6+, Safari 6.0.2+, Chrome 7+, and IE 10+.
I believe for CloudCode the easiest solution is 2. The thing that was tripping me earlier is that I didn't notice it expects an Object with the format { base64: {{your base64 encoded data here}} }.
Also Parse.Files can only be set to a Parse.Object after being saved (this behaviour is also present on all client SDKs). I strongly recommend using the Promise version of the API as it makes much easier to compose such asynchronous operations.
So the following code will solve your problem:
Parse.Cloud.httpRequest({...}).then(function (httpImgFile) {
var data = {
base64: httpImgFile.buffer.toString('base64')
};
var file = new Parse.File("file", data);
return file.save();
}).then(function (file) {
fbPerson.set("profilePicture", file);
return fbPerson.save();
}).then(function (fbPerson) {
// fbPerson is saved with the image
});

Related

ApplePay completeMerchantValidation fails

We have a site example.com behind ssl that runs a page with ApplePay.
We've got a server side that returns a Merchant Session that looks like the following:
{"epochTimestamp":1581975586106,"expiresAt":1581979186106,"merchantSessionIdentifier":"SSH8E666B0...","nonce":"1239e567","merchantIdentifier":"...8557220BAF491419A...","domainName":"example.com","displayName":"ApplePay","signature":"...20101310f300d06096086480165030402010500308..."}
We receive this response in session.onvalidatemerchant as a string and convert it to a Json Object and pass to session.completeMerchantValidation.
As a result we get the following error:
Code: "InvalidAccessError"
Message: "The object does not support the operation or argument"
We run the following code on our page:
.....
session.onvalidatemerchant = (event) => {
const validationURL = event.validationURL;
getApplePaySession(validationURL).then(function (response) {
try {
let resp = JSON.parse(response);
session.completeMerchantValidation(resp);
} catch (e) {
console.error(JSON.stringify(e));
}
});
};
....
Additional questions:
Is the object described above a "correct" Merchant Session opaque that needs to be passed to completeMerchantValidation or it's missing some fields?
Is this object needs to be passed as is or it needs to be base64 encoded?
Does it need to be wrapped into another object?
Any help or lead is greatly appreciated.

Google Cloud Platform: Unable to upload a new file version in Storage via API

I wrote a script that uploads a file to a bucket in Google Cloud Storage:
Ref: https://cloud.google.com/storage/docs/json_api/v1/objects/insert
function submitForm(bucket, accessToken) {
console.log("Fetching the file...");
var input = document.getElementsByTagName('input')[0];
var name = input.files[0].name;
var uploadUrl = 'https://www.googleapis.com/upload/storage/v1/b/'+
bucket + '/o?uploadType=media&access_token=' + accessToken + '&name=' + name;
event.preventDefault();
fetch(uploadUrl, {
method: 'POST',
body: input.files[0]
}).then(function(res) {
console.log(res);
location.reload();
})
.catch(function(err) {
console.error('Got error:', err);
});
}
It works perfectly fine when uploading a new file.
However, I get a 403 status code in the API response body while trying to replace an existing file with a new version.
Please note that:
The OAuth 2.0 scope for Google Cloud Storage is: https://www.googleapis.com/auth/devstorage.read_write
I did enable the versioning for the destination bucket
Could someone help me in pointing out what I did wrong?
Update I:
As suggested, I am trying to invoke the rewrite function as follows:
const input = document.getElementsByName('uploadFile')[0];
const name = input.files[0].name;
const overwriteObjectUrl = 'https://www.googleapis.com/storage/v1/' +
'b/' + bucket +
'/o/' + name +
'/rewriteTo/b/' + bucket +
'/o/' + name;
fetch(overwriteObjectUrl, {
method: 'POST',
body: input.files[0]
})
However, I am getting a 400 (bad request error).
{"error":{"errors":[{"domain":"global","reason":"parseError","message":"Parse Error"}],"code":400,"message":"Parse Error"}}
Could you explain me what I am doing wrong?
Update II:
By changing body: input.files[0] with body: input.files[0].data I made it working... Theoretically!
I get a positive response body:
{
"kind":"storage#rewriteResponse",
"totalBytesRewritten":"43",
"objectSize":"43",
"done":true,
"resource":{
"kind":"storage#object",
"id":"mybuck/README.txt/1520085847067373",
"selfLink":"https://www.googleapis.com/storage/v1/b/mybuck/o/README.txt",
"name":"README.txt",
"bucket":"mybuck",
"generation":"1520085847067373",
"metageneration":"1",
"contentType":"text/plain",
"timeCreated":"2018-03-03T14:04:07.066Z",
"updated":"2018-03-03T14:04:07.066Z",
"storageClass":"MULTI_REGIONAL",
"timeStorageClassUpdated":"2018-03-03T14:04:07.066Z",
"size":"43",
"md5Hash":"UCQnjcpiPBEzdl/iWO2e1w==",
"mediaLink":"https://www.googleapis.com/download/storage/v1/b/mybuck/o/README.txt?generation=1520085847067373&alt=media",
"crc32c":"y4PZOw==",
"etag":"CO2VxYep0NkCEAE="
}
}
Whit as well a new generation number (versioning enabled).
However, the file content has been not updated: I did append new strings but they did not show off within the file. Do you have any idea?
Thanks a lot in advance.
Based on the information available it's difficult to diagnose this issue with certainty- however I would check the roles assigned to the user or service account you are using for this operation.
As you have been able to upload a file, but not overwrite a file, this sounds like you may have assigned the user or service account that is attempting to perform this task the 'Storage Object Creator' role.
Users/service accounts with the Storage Object Creator role can create new objects in buckets but not overwrite existing ones (you can see this mentioned here).
If this is the case, you could try assigning the user/service account the role of 'Storage Object Admin' which allows users full control over bucket objects.
"insert" is only to be used to create new objects per the Methods section of the API's documentation, so you'll need to use "rewrite" to rewrite an existing object.

Nativescript send camera capture to server

In my Nativescript application I would like to capture an image using the camera module and then send the bytes directly to the server via http call.
Here is my code (incomplete for brevity):
var cameraModule = require("camera");
var http = require("http");
...
cameraModule.takePicture().then(function (img) {
// how to extract the actual bytes from img???
http.request({
url: some_url,
method: "POST",
headers: { "Content-Type": "application/octet-stream" },
content: ???
});
});
Is there a way to do that?
I was looking at nativescript-background-http and it seems to fit my requirements exactly, but the example shows the file being loaded from a path only. I did not have any luck making this to work on iOS.
Any help is greatly appreciated.
Thank you.
A couple things;
"img" is actually a image source.
At this point the built in HTTP module does not support direct binary transfers, so we need to convert it to something that can be sent over the wire. So base64 is a text representation that can support binary, and it is a common encoding/decoding method.
Since we already have it as a image source we just use the cool toBase64String ability which give us the Base 64 data.
So here is basically is how I would do it (tested under android).
var cameraModule = require('camera');
var some_url="http://somesite";
// img is a image source
cameraModule.takePicture().then(function (img) {
// You can use "jpeg" or "png". Apparently "png" doesn't work in some
// cases on iOS.
var imageData = img.toBase64String("jpeg");
http.request({
url: some_url,
method: "POST",
headers: { "Content-Type": "application/base64" },
content: imageData
}).then(function() {
console.log("Woo Hoo, we sent our image up to the server!");
}).catch(function(e) {
console.log("Uh oh, something went wrong", e);
});
});
There are a few ways to do this. If your backend can take a base64 string you can use the image-source class and manipulate the data. I'm on my phone or I'd mock up a sample. It really depends what you expect on the server to be honest but most options are possible with NativeScript using the image-source and ui/image component.
http://docs.nativescript.org/api-reference/classes/_image_source_.imagesource.html#tobase64string
Going from memory here but try this when you get the (IMG) back.
var data = img.tobase64string(); that should give you a base 64 string of the image.
Just found this awesome sample from another question https://stackoverflow.com/a/37815237/1893557
This will work to send the file after you save it locally and uses the background-http plugin.

jQuery Ajax - Cant parse json?

I got a very strange problem, I thought this worked before but it doesn't any more. I dont even remember changing anything. I tried with an older jQuery library.
I got an error that says: http://i.imgur.com/H51wG4G.png on row 68: (anonymous function). which refer to row 68:
var jsondata = $.parseJSON(data);
This is my ajax function
I can't get my alert to work either because of this error. this script by the way is for logging in, so if I refresh my website I will be logged in, so that work. I also return my json object good as you can see in the image. {"success":false,"msg":"Fel anv\u00e4ndarnamn eller l\u00f6senord.","redirect":""}
When I got this, I will check in login.success if I got success == true and get the login panel from logged-in.php.
$('#login_form').submit(function()
{
var login = $.ajax(
{
url: '/dev/ajax/trylogin.php',
data: $(this).serialize(),
type: 'POST',
}, 'json');
login.success(function(data)
{
var jsondata = $.parseJSON(data);
console.log(jsondata);
if(jsondata.success == true)
{
$.get("/dev/class/UI/logged-in.php", function(data) {
$(".login-form").replaceWith(data);
});
}
else
{
alert(jsondata.msg);
$('#pwd').val('');
}
});
return false;
});
Thank you.
If the response you have showed in the attached screenshot is something to go by, you have a problem in your PHP script that's generating the JSON response. Make sure that thePHP script that's generating this response (or any other script included in that file) is not using a constant named SITE_TITLE. If any of those PHP files need to use that constant, make sure that that SITE_TILE is defined somewhere and included in those files.
What might have happened is that one of the PHP files involved in the JSON response generation might have changed somehow and started using the SITE_TITLE costant without defining it first, or without including the file that contains that constant.
Or, maybe none of the files involved in the JSON generation have changed, but rather, your error_reporting settings might have changed and now that PHP interpreter is outputting the notice level texts when it sees some undefined constant.
Solving the problem
If the SITE_TITLE constant is undefined, define it.
If the SITE_TITLE constant is defined in some other file, include that file in the PHP script that's generating the response.
Otherwise, and I am not recommending this, set up your error_reporting settings to ignore the Notice.
Your response is not a valid JSON. You see: "unexpected token <".
It means that your response contains an unexpected "<" and it cannot be converted into JSON format.
Put a console.log(data) before converting it into JSON.
You shoud use login.done() , not login.success() :)
Success is used inside the ajax() funciton only! The success object function is deprecated, you can set success only as Ajax() param!
And there is no need to Parse the data because its in Json format already!
jQuery Ajax
$('#login_form').submit(function()
{
var login = $.ajax(
{
url: '/dev/ajax/trylogin.php',
data: $(this).serialize(),
type: 'POST',
}, 'json');
login.done(function(data)
{
var jsondata = data;
console.log(jsondata);
if(jsondata.success == true)
{
$.get("/dev/class/UI/logged-in.php", function(data) {
$(".login-form").replaceWith(data);
});
}
else
{
alert(jsondata.msg);
$('#pwd').val('');
}
});
return false;
});

JSONP pass api key

I've got an arduino uploading sensor data to cosm.com. I made a simple webpage on my local web server to query the cosm.com API and print out the values.
The problem is that if I am not logged into cosm.com in another tab, I get this popup.
The solution is to pass my public key to cosm.com, but I am in way over my head here.
The documentation gives an example of how to do it in curl, but not javascript
curl --request GET --header "X-ApiKey: -Ux_JTwgP-8pje981acMa5811-mSAKxpR3VRUHRFQ3RBUT0g" https://api.cosm.com/v2/feeds/120687/datastreams/sensor_reading
How do I pass my key into the url?:
function getJson() {
$.ajax({
type:'GET',
url:"https://api.cosm.com/v2/feeds/120687/datastreams/sensor_reading",
//This line isn't working
data:"X-ApiKey: -Ux_JTwgP-8pje981acMa5811-mSAKxpR3VRUHRFQ3RBUT0g",
success:function(feed) {
var currentSensorValue = feed.current_value;
$('#rawData').html( currentSensorValue );
},
dataType:'jsonp'
});
}
UPDATE:
It must be possible because hurl.it is able to query the api
http://www.hurl.it/hurls/75502ac851ebc7e195aa26c62718f58fecc4a341/47ad3b36639001c3a663e716ccdf3840352645f1
UPDATE 2:
While I never did get this working, I did find a work around. Cosm has their own javascript library that does what I am looking for.
http://cosm.github.com/cosm-js/
http://jsfiddle.net/spuder/nvxQ2/5/
You need to send it as a header, not as a query string, so try this:
function getJson() {
$.ajax({
type:'GET',
url:"https://api.cosm.com/v2/feeds/120687/datastreams/sensor_reading",
headers:{"X-ApiKey": "-Ux_JTwgP-8pje981acMa5811-mSAKxpR3VRUHRFQ3RBUT0g"},
success:function(feed) {
var currentSensorValue = feed.current_value;
$('#rawData').html( currentSensorValue );
},
dataType:'jsonp'
});
}
It should be much easier to get it to work using CosmJS. It is an officially supported library and provides full coverage of Cosm API.

Resources