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/
Related
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.
I made two classes in parse User(by default) and UserData.
BeforeSave Trigger as follows:
Parse.Cloud.beforeSave(Parse.User, function(request, response) {
var userDataObject = new Parse.Object("UserData");
var fromUserPointer = {"__type":"Pointer","className":"_User","objectId":request.object.id};
return userDataObject.save({score: 0, ideasCount: 0, followersCount:0, return:0}).then(function (userData) {
var userDataPointer = {"__type":"Pointer","className":"UserData","objectId":userData.id};
request.object.set("userData", userDataPointer);
response.success();
}, function(error) {
response.error(error.message);
});
});
It saves user's UserData and takes its UserData pointer field and saves in UserData class.
Parse.Cloud.afterSave(Parse.User, function(request) {
Parse.Cloud.useMasterKey();
var userPointer = {"__type":"Pointer","className":"_User","objectId":request.object.id};
var userData = request.object.get("userData");
if (userData) {
var userDataPointer = {"__type":"Pointer","className":"UserData","objectId":userData.id};
var userDataQuery = new Parse.Query("UserData");
userData.set("user", userPointer);
return userData.save().then (function (userData) {
var activityObject = new Parse.Object("Activity");
return activityObject.save({fromUserData: userDataPointer, from:userPointer,
toUserData:userDataPointer, to:userPointer, type:"follow"});
}).then (function (success) {
}, function (error) {
console.error("Error in afterSave(user) : " + request.object.id + ":" + error.message);
});
}
});
The problem is that, before saving in the User class, it sometimes does not create UserData, which it should create. Hence these two triggers must run atomically, which they do not.
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.
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);
});
});
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('');
}