Changes to CloudCode for Open source Parse - parse-platform

My cloud code returns this error when I run it ever since migrating to Azure. It worked fine before migrating. I do recall seeing a post about needing to change some parts of cloud code (e.g. Parse.Cloud.useMasterKey();) now that Parse has gone open source, but I cannot find it anywhere.
Here's the error:
2016-04-20 10:01:37.627 App Name [Error]: {
result = Fail;
} (Code: 141, Version: 1.12.0)
2016-04-20 10:01:37.628 App Name {
NSLocalizedDescription = {
result = Fail;
};
code = 141;
error = {
result = Fail;
};
temporary = 0;
}
And here's my cloud function:
Parse.Cloud.define("addFriendRelation", function(request, response) {
Parse.Cloud.useMasterKey();
var currentUser=Parse.User.current();
var query = new Parse.Query(Parse.User);
var userId = request.params.userId;
query.get(userId,
{
success: function (object)
{
console.log(object.objectId);
var toUserFriend = object.relation("friends");
toUserFriend.add(currentUser);
object.save();
console.log("Success");
var jsonObject = {
"result" : "Success"
};
response.success(jsonObject);
},
error: function (object, error)
{
console.log("Fail");
var jsonObject={
"result" : "Fail"
};
response.error(jsonObject);
}
});
});
Thank you!

I believe the issue you are having originates from where you have
var currentUser = Parse.User.current();
This code is wrong.
You can however get the user that made the request using.
var user = request.user;

Related

Getting a 403 Forbidden error on plugin request

I'm trying to fire a plugin request from my ICN plugin. The request goes as below. However, I'm getting a 403 Forbidden error from the server.
Forbidden
You don't have permission to access /navigator/jaxrs/plugin on this server.
https://<icnserver.com>/navigator/jaxrs/plugin?repositoryId=Demo&query=%5B%7B%22name%22%3A%22ID%22%2C%22operator%22%3A%22LIKE%22%2C%22values%22%3A%5B%22123434234%22%2C%22%22%5D%7D%5D&className=Checks&plugin=DemoPlugin&action=DemoService&desktop=Demo
Plugin JS:
aspect.around(ecm.model.SearchTemplate.prototype, "_searchCompleted", function advisingFunction(original_searchCompleted){
return function(response, callback, teamspace){
var args = [];
var templateName = response.templates[0].template_name;
var res = response;
var requestParams = {};
requestParams.repositoryId = this.repository.id;
requestParams.query = query;
requestParams.className = templateName;
Request.invokePluginService("DemoPlugin", "DemoService",
{
requestParams: requestParams,
requestCompleteCallback: lang.hitch(this, function(resp) { // success
res.rows = resp.rows;
res.num_results = resp.rows.length;
res.totalCount = resp.rows.length;
args.push(res);
args.push(callback);
args.push(teamspace);
original_searchCompleted.apply(this,args);
})
}
);
}
});
You need to provide a security_token to be able to call your service, so you need to login first.
Then, open your browser's debug and check the requests in the network tab.
There you can see that every request that targets the /navigator/jaxrs/* URI will contain it, so something like this will be among the headers:
security_token: 163594541620199174
So my bet is that you have not set it in your client (I recommend a postman to test your service, or I would add a test (ICN) feature page in the ICN plugin project in order to be able to call it properly). In your feature page, you can call your service directly using the ecm/model/Request OOTB navigator dojo/javascript class, as you can see in CheckinAction.js:
_checkInDocument: function (item, requestData)
{
var self = this;
var payLoadObject = {requestType: "Get", id: item.id};
Request.postPluginService("DocuSignPlugin", "UpdateSignedDocumentService", "application/json", {
requestParams: {
repositoryId : item.repository.id,
serverType : item.repository.type,
docId : item.docid,
envelopeId: item.attributes.DSEnvelopeID,
payLoad: json.stringify(payLoadObject)
},
requestCompleteCallback: function(response) {
if (response.returncode == 0)
{
item.attributeDisplayValues.DSSignatureStatus = "Checkedin";
item.attributes.DSSignatureStatus = 4;
item.update(item);
}
else if (response.returncode == -1)
{
items = [];
items.push(item);
self._showLoginDialog(items);
}
},
backgroundRequest : false,
requestFailedCallback: function(errorResponse) {
// ignore handline failures
}
});
},
As you can see, you don't have to add the security_token to the requestParams, the framework will do it for you.

Update Parse user via Cloud Code

I'm trying to update some attributes on my user via cloud code, but even when there is no error, nothing is being updated??? Any thoughts?
Parse.Cloud.define("updateDetailsUser", function (request, response) {
var query = new Parse.Query("User");
query.equalTo("objectId", request.user.id);
var mobileNumber = request.params.mobileNumber;
var fullName = request.params.fullName;
var email = request.params.email;
query.first({
success: function (user) {
user.set("mobileNumber", mobileNumber);
user.set("fullName", fullName);
user.set("email", email);
user.save(null, {
useMasterKey: true,
success: function (updated) {
}
});
}
});
});
For all the classes that are built-in, it suggests to use the Parse class name for them. In case of User, you need to use Parse.User.
So, to fix this, just replace
var query = new Parse.Query("User"); with var query = new Parse.Query(Parse.User); and it should work.
To read further : http://parseplatform.org/Parse-SDK-JS/api/

Parse Cloud - Get user informations by objectId

I'm trying to get user lang from User class in Parse Cloud. lang is one of the columns in User class. I wanna get lang of the user. My entire Cloud Code is as following (it didn't work):
Parse.Cloud.beforeSave('Order', function(request, response) {
var orderState = request.object.get('orderState');
var subtitleMessage = '';
var userLang = '';
var currentUser = request.object.get('user');
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo('objectId', currentUser.id);
.find()
.then((result)=>{
userLang = result.get('lang');
})
if (orderState === undefined || ['nonApproved', 'approved', 'delivered', 'canceled'].indexOf(orderState) < 0) {
response.error("OrderState is null or not one the ['nonApproved', 'approved', 'delivered', 'canceled']!");
} else {
var query = new Parse.Query(Parse.Installation);
query.include('user');
query.equalTo('user', request.object.get('user'));
Parse.Push.send(
{
where: query,
data: {
title: "MyTitle",
alert: subtitleMessage
}
},
{
success: function() {
},
error: function(error) {
response.error(error)
},
useMasterKey: true
}
);
response.success();
}
});
The answer from Jake T. has some good points. Based on his answer and your comment on the question, you could try something like this:
Parse.Cloud.beforeSave('Order', function(request, response) {
var currentUser = request.object.get('user');
currentUser.fetch({useMasterKey: true}).then(function(user) {
var userLang = user.get('lang');
// send push notifications based on userLang here
response.success();
}).catch(function(error) {
// handle any errors here
console.error(error);
});
});
Verify you actually have a User object shell from request.object.get("user"); And, if you do, you can just call currentUser.fetch() instead of performing a query, unless there are other objects you may need to include.
Since you used a query, the result is an array, even if there is only a single object returned (or none, it would be simply []). So, you're doing Array.get("lang"), which shouldn't do anything. Try if( results && results.length > 0 ) user = results[0];, then you should be able to access user.get("lang");
You should have ACL / CLP's set up for your User class. Ideally, these should not be accessible by people who are not the user or master. So, if that is set up properly, your solution may be passing {useMasterKey:true} as an option to the query / fetch.

calling a function in Xcode

I have Inventory table in my Parse database with two relevant fields How can I do that with swift ? I create cloud code with Js below
Parse.Cloud.define("retrieveproducts", function(request, response) {
var productDictionary ={};
var query = new Parse.Query("Post");
query.each(
function(result){
var num = result.get("quantity");
if(result.get("productid") in productDictionary){
productDictionary[result.get("productid")] += num;
}
else{
productDictionary[result.get("productid")] = num;
}
}, {
success: function() {
response.success(productDictionary);
},
error: function(error) {
response.error("Query failed. Error = " + error.message);
}
});
});
I want to call this function : but i have some trouble calling it with this call
let params = ["productid": String(), "string": String()]
PFCloud.callFunctionInBackground("retrieveproducts", withParameters: params) {
(ratings, error) in
if (error == nil) {
print("\(params)")
}
}
Swift Code
let reportedId = "someUsersObjectId"
PFCloud.callFunctionInBackground("suspendUser", withParameters: ["userId": reportedId]) {
(result, error) in
if (error == nil) {
print(result)
}
}
Cloud Code:
Parse.Cloud.define("suspendUser", function(request, response) {
Parse.Cloud.useMasterKey()
//var User = Parse.Object.extend(Parse.User);
//var user = new User();
//user.id = request.params.userId;
user = new Parse.User({id:request.params.userId})
user.fetch().then(function() {
user.set("suspended", true)
user.save().then(function(newMostRecentAgain) {
response.success("Cloud code called! " + request.params.userId)
}, function(error) {
// The save failed. Error is an instance of Parse.Error.
})
});
});
So let me walk you through what's going on here, so you can better figure out how to do your code (since I can'e exactly know what you wanna do).
1: in my Swift code, withParameters is how you pass info to your cloud code, and it's in the style of a dictionary. Here I'm passing the user I wanna report's objectId.
PFCloud.callFunctionInBackground("suspendUser", withParameters: ["userId": reportedId]) {
2: In my Cloud code, I'm getting the Parse Object of the user I reported with the objectId I'm passing with the params. Since you can't pass an entire object to the cloud code, I'm rebuilding the object with the objectId and the user.Fetch() you see.
user = new Parse.User({id:request.params.userId})
3: in my Cloud code, after I successfully save my user after changing it's value for "suspended", I send a string back to the IOS user.
response.success("Cloud code called! " + request.params.userId)
4: Finally, in my Swift Code, I then print the returned string from success
print(result)
Does this make things a little bit more clear? Let me know if anything doesn't make sense.

Fetching Images through Cloud Code

I've been scratching my head over this for a while. What am I doing wrong? Your help is much appreciated :)
I've tried many different image codes, but I think it's a promise issue I'm seeing. With the code below I only see the "Start of loop" log message.
If I move the results push outside the promise structure to underneath then I see the Stage log messages, albeit after all the Start of loops have printed (hence why I put the push in the then function).
Parse.Cloud.job("fetchjson", function(request, status) {
var url = 'some json url';
Parse.Cloud.httpRequest({url: url}).then(function(httpResponse){
//var Image = require("parse-image");
var Seeds = Parse.Object.extend("Seeds");
var jsonobj = JSON.parse(httpResponse.text);
var results = [];
// do NOT iterate arrays with `for... in loops`
for(var i = 0; i < jsonobj.seeds.length; i++){
var seed = new Seed();
var a = new Seed(jsonobj.seeds[i]);
console.log("Start of loop");
Parse.Cloud.httpRequest({url: a.get("image") }).then(function(response) {
console.log("Stage 1");
//var file = new Parse.File('thumb.jpg', { base64: response.buffer.toString('base64', 0, response.buffer.length) });
//return file.save();
return "hi"
}).then(function(thumb) {
console.log("Stage 2");
//a.set("imageFile", thumb);
//a.set("viewsInt", parseInt(a.get("views")));
}, function(error) {
console.log("Error occurred :(");
}).then(function(){
results.push(seed.save(a)); // add to aggregate
});
}
// .when waits for all promises
Parse.Promise.when(results).then(function(data){
status.success("All saved");
});
}, function(error) {
console.error('Request failed with response code ' + httpResponse.status);
status.error("Failed");
});
});

Resources