User object not saving in afterSave code - parse-platform

I have tried multiple variations of this and for some reason the field "Followers" is not being incremented:
ParseObject follow = new ParseObject("Follow");
follow.put("from", currentUser);
follow.put("to", parseUser);
follow.put("approved", approved);
Then in cloud code:
Parse.Cloud.afterSave("Follow", function(request) {
var to = request.object.get("to");
var query = new Parse.Query(Parse.User);
query.equalTo("objectId", to.id);
query.first({
success: function(user) {
user.increment("Followers");
user.save();
console.log("User: " + user.id + " Followers: " + user.get("Followers"));
}, error: function(error) {
console.log("afterSave: " + error);
}
});
var currentUser = Parse.User.current();
currentUser.increment("Following");
currentUser.save();
});
According to the logs it is working:
I2015-11-28T18:21:54.745Z]v47 after_save triggered for Follow for user k0ZvNAy3Mk:
Input: {"object":{"approved":false,"createdAt":"2015-11-28T18:21:54.743Z","from":{"__type":"Pointer","className":"_User","objectId":"k0ZvNAy3Mk"},"objectId":"JQBO9m21uA","to":{"__type":"Pointer","className":"_User","objectId":"bcpbFaXj9C"},"updatedAt":"2015-11-28T18:21:54.743Z"}}
Result: Success
I2015-11-28T18:21:54.906Z]User: bcpbFaXj9C Followers: 1
But when I look at the data the Followers field for that user still says 0
I have also tried:
Parse.Cloud.afterSave("Follow", function(request) {
var to = request.object.get("to");
to.increment("Followers");
to.save();
var currentUser = Parse.User.current();
currentUser.increment("Following");
currentUser.save();
});
According to the docs since it is a pointer I should be able to manipulate it directly but that did not work either.
Any ideas what to do or why this is not working correctly?

save() is asynchronous function, you should not leave the function before it is completed. Use this:
user.save().then(function(success){
console.log("User: " + success.id + " Followers: " + success.get("Followers"));
}, function (error){
console.log(error.message);
});

Looks like the parse cloud code depends on the user that is currently logged in and manipulating data on another user is not allowed unless you are logged in as them.
Parse.Cloud.afterSave("Follow", function(request) {
Parse.Cloud.useMasterKey(); // Needed this
var to = request.object.get("to");
to.increment("Followers");
to.save();
var currentUser = Parse.User.current();
currentUser.increment("Following");
currentUser.save();
});

Related

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.

Update user object from Parse cloud code is not saving

Currently I am trying to update the username and password from parse cloud code, but In the parse.com console I am seeing the success messages, but the object is not actually saved in the parse.com database. Here is the contents of cloud/main.js
// code to update username
Parse.Cloud.define("updateUserName", function(request, response){
if(!request.user){
response.error("Must be signed in to update the user");
return;
}
Parse.Cloud.useMasterKey();
var userId = request.params.id;
var userName = request.params.userName;
// var User = Parse.Object.extend("User");
var updateQuery = new Parse.Query(Parse.User);
updateQuery.get(userId,{
success: function(userRecord){
console.log(userRecord.get("id"));
userRecord.set("username", userName);
// userRecord.set("resetToken", "Apple");
userRecord.save(null,{
success: function(successData){
response.success("username updated successfully.");
// userRecord.fetch();
},
error: function(errorData){
console.log("Error while updating the username: ",errorData);
}
});
},
error: function(errorData){
console.log("Error: ",errorData);
}
});
});
Parse.Cloud.define("resetPassword", function(request, response){
var successMsg = "";
if(!request.user){
response.error("Must be signed in to update the user");
return;
}
Parse.Cloud.useMasterKey();
var resetToken = request.params.resetToken;
var password = request.params.password;
// var User = Parse.Object.extend("User");
var updateQuery = new Parse.Query(Parse.User);
// updateQuery.equalTo("resetToken", resetToken);
updateQuery.get(resetToken,{
success: function(userRecord){
// console.log(userRecord.get("id"));
// userRecord.set("password",password)
userRecord.set("password",password);
userRecord.save(null, {
success: function(successData){
successMsg = "Password Changed !";
console.log("Password changed!");
userRecord.set("resetToken", "");
userRecord.save();
},
error: function(errorData){
response.error("Uh oh, something went wrong");
}
})
},
error: function(errorData){
console.log("Error: ",errorData);
}
});
response.success(successMsg);
});
The code actually runs without any error, but it is not updating the values in the database. Here is how I am calling these cloud functions in js/index.js
$(".update-user").click(function(){
Parse.Cloud.run("updateUserName", {id: $(this).data("id"), username: $(".uname").val()},
{
success: function(successData){
console.log("username updated successfully.");
$("#editModal").modal("hide");
$(".edit-modal").hide();
},
error: function(errorData){
}
});
});
The contents that I see in the firefox console username updated successfully.
The contents that I see in parse.com console
I2015-12-11T06:15:13.361Z]v106 Ran cloud function updateUserName for user chfgGhaPEl with:
Input: {"id":"MAvm9FlGgg","username":"testuser12"}
Result: username updated successfully.
But this line of code userRecord.set("resetToken", "Apple"); is updating the resetToken column in the database, but why not it is not letting me update the username/password(or other columns that I didn't try updating) columns ?
I analyse your code. Instead of using get to retrieve correlated user, use first where you specify the user id as query constraint. One example (working) code is below where user information is updated in Parse User table. Hope this helps.
Regards.
Parse.Cloud.define("updateUser", function(request, response)
{
Parse.Cloud.useMasterKey();
var query = new Parse.Query(Parse.User);
var objectId = request.params.objectId;
var username = request.params.username;
var email = request.params.email;
var userType = request.params.userType;
var password = request.params.password;
query.equalTo("objectId", objectId);
query.first({
success: function(object)
{
object.set("username", username);
object.set("email", email);
object.set("userType", userType);
object.set("password", password);
object.save();
response.success("Success");
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
response.error("Error");
}
});
});
What worked for me is
//cloud/main.js
Parse.Cloud.define("updateUserName", function(request, response){
if(!request.user){
response.error("Must be signed in to update the user");
return;
}
if(request.params.IsAdmin == false){
response.error("Only the administrators can edit username.");
return;
}
Parse.Cloud.useMasterKey();
// var userId = request.params.Id; --> I guess he was the main culprit, the params and the actual column value should match. Instead of passing Id from my client code(see below) I just passed objectId and it worked.
var userId = request.params.objectId;
// var userName = request.params.username;
var name = request.params.name;
// var User = Parse.Object.extend("User");
var updateQuery = new Parse.Query(Parse.User);
console.log("id from params: "+userId);
updateQuery.equalTo("objectId", userId);
updateQuery.first({
success: function(userRecord){
// userRecord.set("username", userName);
userRecord.set("name", name);
userRecord.save(null,{
success: function(successData){
response.success("username updated successfully.");
userRecord.fetch();
},
error: function(errorData){
console.log("Error while updating the username: ",errorData);
}
});
},
error: function(errorData){
console.log("Error: ",errorData);
response.error(errorData);
}
});
});
// js/index.js
/* initially I was using Id instead of objectId, the field names are case
sensitive
Parse.Cloud.run("updateUserName", {id: $(this).data("id"), name: $(".name").val(),IsAdmin: Parse.User.current().get("IsAdmin") },*/
Parse.Cloud.run("updateUserName", {objectId: $(this).data("id"), name: $(".name").val(),IsAdmin: Parse.User.current().get("IsAdmin") },
{
success: function(successData){
console.log("username updated successfully.");
$("#editModal").modal("hide");
$(".edit-user-server-error").html("");
$(".edit-modal").hide();
location.reload();
},
error: function(errorData){
console.log(errorData);
$(".edit-user-server-error").html("");
$(".edit-user-server-error").html(errorData.message);
}
});
So I had referred to this post and it gave me an hint, based on that I just did one trial and error thing and got it working.
You can pass any sort of values in the parameters to this Cloud Function, so you might want to specify exactly which properties you wish to update in this manner. Also, don't forget to actually validate that request.user is allowed to perform such an operation.
Parse doesn't support HTTP PUT requests to save the data. Hence we need to use PUSH request containing a method call to save the data.
However it has to have a the line, Parse.Cloud.useMasterKey(); before calling the save method.

why save event is not working in cloud code?

Find my code below which working very fine. but only problem facing by me is that save event is not working for me.Also you can see my log file in the picture. In each method i tried success and error function which working fine as you can see in picture. I tried this code alot but still... it is not working for me.
It always shows error message.
Code :
Parse.Cloud.afterSave("HouserDetailed", function(request, response)
{
var obj = request.object.id;
//console.log(obj);
// code !
var houserdetailed = new Parse.Object("HouserDetailed");
var query = new Parse.Query("HouserDetailed");
query.equalTo("objectId", obj);
query.first({
success: function(results) {
//alert("updates objectId " +request.object.id + " " + "input" + " "+ request.object.bet_title );
var bet_title = results.get("bet_title");
var match_id = results.get("match_id");
var level_coin = results.get("level_coin");
if(bet_title !== "false")
{
console.log("bet_title :- "+bet_title+", match_id:- "+match_id+", level_coin:- "+level_coin);
// nested query
var better = new Parse.Object("Better");
var query1 = new Parse.Query("Better");
query1.equalTo("match_id", match_id);
query1.first({
success: function(result){
var bet_title_better = result.get("bet_title");
var user_id = result.get("user_id");
var bet_OnNoOfticket = result.get("bet_OnNoOfticket");
var bet_price = result.get("bet_price");
var money_got = bet_OnNoOfticket * bet_price;
console.log("bet_title_better :-"+bet_title_better);
if(bet_title !== bet_title_better)
{
console.log("Condition does not match!");
}
else
{
console.log("Condition match!" + "money got :- "+money_got);
// checking for existing user in parse DB
var wallet = new Parse.Object("Wallet");
var query2 = new Parse.Query("Wallet");
query2.equalTo("user_id", user_id);
query2.first({
success: function(result)
{
console.log("User found");
var wallet_coins_number = result.get("wallet_coins_number");
var objectId = result.get("objectId");
total_amount = +wallet_coins_number + +money_got;
console.log("Total amount got :- " + total_amount );
// saving amount in wallet
var Wallet = Parse.Object.extend("Wallet");
var wallet = new Wallet();
wallet.set("user_id", user_id);
wallet.set("wallet_coins_number", total_amount);
wallet.save(null, {
success: function(wallet){
console.log("amount saved in wallet!");
},
error: function(wallet)
{
console.log("amount not saved in wallet!");
}
});
},
error: function(error)
{
console.log("User not found");
}
});
}
},error: function(error)
{
}
});
}
// nested query end
},
error: function(error) {
console.log("Error: " + error.code + " " + error.message);
}
});
// code !
});][1]][1]
I don't see any log, probably it would tell you what is wrong. But you are attempting to save existing ParseObject with dirty objectId, which is bad idea. You are not allowed to change objectId of existing object. Try to remove wallet.set("objectId", objectId) from your code.
You should not use result.get("objectId") either, use result.id instead.

Object from Pointer in Parse Cloud Code

I'm attempting to create my first Parse Cloud Code function and am running into an issue:
Parse.Cloud.afterSave("Message", function(request) {
var fromUser = request.object.get("fromUser");
var toUser = request.object.get("toUser");
console.log(fromUser); // user pointer
console.log(toUser); // user pointer
});
As you can see both fromUser and toUser is a pointer when what I actually want is the user objects themselves. What is the best way to do this?
You can create a new query to get user informations.
var query = new Parse.Query(Parse.User);
query.get(request.object.get('fromUser').id, {
success: function(user) {
// What you want with user informations
},
error: function() {}
});
You can try this, but I've never try.
var query = new Parse.Query(Parse.User);
query.equalTo('objectId', request.object.get('fromUser').id);
query.equalTo('objectId', request.object.get('toUser').id);
query.find({
success: function(users) {
// What you want with users information
},
error: function() {}
});
I am too late, but I hope this will work
you can use
Parse.Cloud.beforeSave("Message", function(request, response) { ....
or
Parse.Cloud.afterSave("Message", function(request) { ....
.
this is how to use beforeSave
Parse.Cloud.beforeSave("Message", function(request, response) {
var message = request.object;
var fromUser = message.get("fromUser"); // you must have this User object, if it's null, then the object is null in the table
var toUser = message.get("toUser");
// fromUser and toUser columns must be Pointer<User> and have values
}).catch(function(error) {
response.error("Error finding message " + error.code + ": " + error.message);
});
});

Setting a Parse.Object.relation at/after object creation

My Email object (my own custom class) is being written though the relation is not being set on time, any ideas how to chain this properly?
// Create new Email model and friend it
addFriendOnEnter: function(e) {
var self = this;
if (e.keyCode != 13) return;
var email = this.emails.create({
email: this.emailInput.val(),
ACL: new Parse.ACL(Parse.User.current())
});
var user = Parse.User.current();
var relation = user.relation("friend");
relation.add(email);
user.save();
this.emailInput.val('');
}
Thanks!
Gon
Because talking to Parse's servers is asynchronous, Parse.Collection.create uses a Backbone-style options object with a callback for when the object is created. I think what you want to do is:
// Create new Email model and friend it
addFriendOnEnter: function(e) {
var self = this;
if (e.keyCode != 13) return;
this.emails.create({
email: this.emailInput.val(),
ACL: new Parse.ACL(Parse.User.current())
}, {
success: function(email) {
var user = Parse.User.current();
var relation = user.relation("friend");
relation.add(email);
user.save();
self.emailInput.val('');
}
});
}
Got it!
The .create method on the this.emails collection does not actually return an object, so var email was empty. Somehow Parse guess it was an empty object of class Email, so I guess the structure is the only thing that remained once .create did its job.
Instead I retrieve the email object on the server using .query, .equalTo and .first
// Create new Email model and friend it
addFriendOnEnter: function(e) {
var self = this;
if (e.keyCode != 13) return;
this.emails.create({
email: this.emailInput.val(),
ACL: new Parse.ACL(Parse.User.current())
});
var query = new Parse.Query(Email);
query.equalTo("email", this.emailInput.val());
query.first({
success: function(result) {
alert("Successfully retrieved an email.");
var user = Parse.User.current();
var relation = user.relation("friend");
relation.add(result);
user.save();
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
this.emailInput.val('');
}

Resources