Parse.com fails when changing user password in beforeSave - parse-platform

I'm trying to reset the passwords of certain test users to a known state for integration testing purposes. However, the line
user.set("password", "testpassword");
Causes the save request to fail with:
Error Domain=Parse Code=141 "The operation couldn’t be completed. (Parse error 141.)"
Here is the relevant beforeSave code:
Parse.Cloud.beforeSave(Parse.User, function(request, response) {
var user = request.object;
Parse.Cloud.useMasterKey();
if (user.get("username").substring(0, 4) === "test") {
console.log("overwriting password for test user.");
user.set("password", "testpassword");
}
response.success();
});

for a full writeup on code 141 check out my other post:
https://stackoverflow.com/a/25360806/3204895
but in this case I'd guess that you're simply accessing the fields in a way that Parse doesn't allow, I see that you're using the master key already so the ACL shouldn't be blocking you, but try using the reserved methods for accessing username and setting the password:
if (user.getUsername().substring(0, 4) === "test") {
console.log("overwriting password for test user.");
user.setPassword("testpassword");
}
if it's that the response.success is happening at the wrong point, although the code looks just fine, account for the async with a promise:
user.save({
password: "testpassword"
}).then(function(savedUser) {
// The save was successful.
response.success(savedUser.getUsername() + "now has a password of 'testpassword'");
}, function(error) {
// The save failed. Error is an instance of Parse.Error.
response.error(user.getUsername() + " saving failed with an error | code: " + error.code + " | message: " + error.message);
});

Related

Cloud Code Error in Saving user

I have a function in my cloud code, which works, but I'm not sure how to fix a problem related to it.
Original Problem:
Parse.Cloud.define("assignTokenToUser", function(request, response) {
console.log("Inside assignTokenToUser");
var token = Math.random().toString(30).substring(7);
query = new Parse.Query("User"),
email = request.params.email;
query.equalTo("username", email);
query.find({ useMasterKey: true }).then(function(results) {
query.first({
success: function(user) {
// Successfully retrieved the object.
user.set("emailToken", token);
user.save();
console.log("success...");
response.success(token);
},
error: function(error) {
console.log("error 1...");
response.error(error);
}
});
}, function(error) {
console.log("error 2...");
response.error(error);
});
});
This seemed to be a common problem after scanning the internet, and my analysis is that the useMasterKey needs to be passed each time we use the query object. Correspondingly, my log file shows that when trying to save the user, it gives a Code 206 error.
Log file output:
Inside assignTokenToUser
success...
^[[32minfo^[[39m: Ran cloud function assignTokenToUser for user undefined with:
Input: {"email":"maryam.zafar#emumba.com"}
Result: "p66qm34jd80p0j6ne03fe1q7f" functionName=assignTokenToUser, email=maryam.zafar#emumba.com, user=undefined
going to send an email... with result: p66qm34jd80p0j6ne03fe1q7f
fullLink: https://beatthegym.com/emailVerified?username=maryam.zafar#emumba.com&token=p66qm34jd80p0j6ne03fe1q7f
^[[31merror^[[39m: Error generating response. ParseError { code: 206, message: 'Cannot modify user 4m0VZFsKVt.' } code=206, message=Cannot modify user 4m0VZFsKVt.
[object Object]
So I went on to change my code to the following:
Code:
Parse.Cloud.define("assignTokenToUser", function(request, response) {
console.log("Inside assignTokenToUser");
var token = Math.random().toString(30).substring(7);
query = new Parse.Query("User"),
email = request.params.email;
query.equalTo("username", email);
query.find({ useMasterKey: true }).then(function(results) {
console.log("inside query.find...");
query.first(null, { useMasterKey: true }).then(function(user) {
console.log("inside query.first...");
// Successfully retrieved the object.
user.set("emailToken", token);
user.save(null, { useMasterKey: true }).then(function() {
console.log("inside user.save...");
response.success();
}, function(error) {
response.error(error);
});
response.success(token);
},
function(error) {
console.log("error 1...");
response.error(error);
});
}, function(error) {
console.log("error 2...");
response.error(error);
});
});
Log file:
Inside assignTokenToUser
inside query.find...
inside query.first...
^[[32minfo^[[39m: Ran cloud function assignTokenToUser for user undefined with:
Input: {"email":"maryam.zafar#emumba.com"}
Result: "tqc8m9lo2tcsrqn69c3q0e1q7f" functionName=assignTokenToUser, email=maryam.zafar#emumba.com, user=undefined
inside user.save...
^[[32minfo^[[39m: Ran cloud function assignTokenToUser for user undefined with:
Input: {"email":"maryam.zafar#emumba.com"}
Result: undefined functionName=assignTokenToUser, email=maryam.zafar#emumba.com, user=undefined
[object Object]
Now, the log file gives me a user as "undefined", and the call to the function gives me a pending status in the Chrome Network tab in the Inspector tool, until it turns into 502, and then the request is auto generated by the browser again. All other requests get a correct 200 response.
However, the data seems to be saved.. the record against this email address saves the token generated correctly. But the request from the browser fails and the user is "undefined" while in the original log file, I see the correct user Id... everytime it fails, the function automatically runs again (because the browser is generating another request everytime it gets a 502) and since it is actually supposed to send an email, it's running again and again keeps on generating infinate emails...
Thank you in advance..
Understood this finally:
The user will remain undefined until and unlesss I obtain it using the Parse.User.current() method. The data does save into the database because it is a forced update to the record, however until the user is aunthenticated using the current() method, it will remain undefined.
I see this is an old post but I spotted clear error in the code:
query = new Parse.Query("User")
Should be:
query = new Parse.Query(Parse.User)
Or at least:
query = new Parse.Query("_User")
As User is a predefined class in Parse.

Parse for javascript - "error 209 invalid session token" when signing up a new user

I wrote a simple function in an angularJS application for signing up new users:
$scope.registerUser = function(username, password) {
var user = new Parse.User();
user.set("username", username);
user.set("email", username);
user.set("password", password);
user.signUp(null, {
success: function(result) {
console.log(result);
$scope.registerUserSuccess = true;
$scope.registerUserError = false;
$scope.registerUserSuccessMessage = "You have successfully registered!";
$scope.$apply();
$timeout(function(){
$state.go("user");
}, 1000);
},
error: function(user, error) {
$scope.registerUserError = true;
$scope.registerUserSuccess = false;
$scope.registerUserErrorMessage = "Error: [" + error.code + "] " + error.message;
$scope.$apply();
}
});
Initially it worked fine, but when I deleted all the users directly through Parse.com, I can't sign up new users using this function anymore. Each time I get error 209 invalid session token. Here's a screenshot of my Parse database:
I've googled the error message and the solution is always to log out the current user. However, if no users exist this isn't an action I can possibly take.
So I would not only like to fix this problem, but also know how to prevent it in the future so my application can be used safely.
Edit: I created a user directly in Parse.com, wrote a function to log in that user, but got the same error. I am completely stuck until this session issue is resolved.
delete all your session tokens, and anything else Parse related really, from local storage:
if needed turn off legacy session tokens, and follow migration tutorial from scratch:
I encountered this same error when building apps with react native using back4app. to clear anything Parse related, from local storage:
add
import { AsyncStorage } from "react-native";
in to the page and Use
AsyncStorage.clear();
See Example Below:
import { AsyncStorage } from "react-native";
import Parse from "parse/react-native";
// Initialize Parse SDK
Parse.setAsyncStorage(AsyncStorage);
Parse.serverURL = "https://parseapi.back4app.com"; // This is your Server URL
Parse.initialize(
"APPLICATION_ID_HERE", // This is your Application ID
"JAVASCRIPT_KEY_HERE" // This is your Javascript key
);
.........
_handleSignup = () => {
// Pass the username, email and password to Signup function
const user = new Parse.User();
user.set("username", "username);
user.set("email", "email");
user.set("password", "password");
user.signUp().then(user => {
AsyncStorage.clear();
if (condition) {
Alert.alert(
"Successful!",
"Signin Successful! Log in to your account.",
[
{
text: "Proceed",
onPress: () => {
//in this example, i navigated back to my login screen
this.props.navigation.navigate("LoginScreen");
}
}
],
{ cancelable: false }
);
}
})
.catch(error => {
Alert.alert("" +error);
});
};

CloudCode User afterSave requires useMasterKey - why?

It woked while ago, but suddenly stopped. Looks like it has something to do with session migration but I don't know why and how to deal with it.
So I've got simple cloud code sample:
Parse.Cloud.define("hello", function(request, response) {
response.success("Hello world!");
});
It works fine naturally.
And I want to run it from afterSave trigger like this:
Parse.Cloud.afterSave(Parse.User, function(request) {
Parse.Cloud.run('hello', { test: 'test'}, {
success: function(success) {
console.log(' Hello success.');
},
error: function(error) {
console.error(' hello failed.');
console.error("Got an error " + error.code + " : " + error.message);
}
});
});
Everything like parse commanded in docs
But when I save user it produces error:
I2015-08-14T06:33:16.709Z] hello failed.
I2015-08-14T06:33:16.711Z]Got an error 209 : invalid session token
How can it be? Am I doing something wrong?
[EDIT]
putting this at the beginning of afterSave trigger helped:
Parse.Cloud.useMasterKey();
I understand this is kind of root command, omitting all ACL restrictions. Can't see where I crossed such restrictions while running simple Hello World function example.

Parse.com: Retrieving object by objectId does not work. Why? It is very simple query

I got an error with message "101 Object not found."
The below code is just copy from the official guide. And I changed the class name and the objectId.
I know this is very simple query but I don't know why? Help me how to debug in this case...
This code is in cloud code. I set up "applicationId" and "masterKey" in global.json.
Thanks..
require('cloud/app.js');
Parse.Cloud.define("sample", function(request, response) {
var GameScore = Parse.Object.extend("Item");
var query = new Parse.Query(GameScore);
query.get("XXXXXX", {
success: function(gameScore) {
},
error: function(object, error) {
console.error("error: " + error.code + " " + error.message);
}
});
});
I tend to use the promise method and I'd possibly rewrite it like this...
Parse.Cloud.define("sample", function(request, response) {
var query = new Parse.Query("Item");
// put this in as a debug message.
console.log("Just checking I'm here!");
query.get("XXXXXX").then (function(item) {
response.success(item);
}, function(error) {
console.error("error: " + error.code + " " + error.message);
response.error(error);
});
});
But it should work as it is. Odd. Are you sure the error message is coming from your code?
Try adding a log before it.
EDIT
It seems that permissions were not set properly on your item object.
With iOS you can specify a default ACL for objects at create time. You can also create a custom ACL object and pass it to the object when saving it.

Parse.com: How do I return the session token?

I've created a signUp function for my app to call, and the Parse.com backend JS code to sign the user up.
Sure enough, the user will appear in the database. Heck, I even got the verification email to be sent (something that was much harder than it should be. It is a setting under the "settings" section of the main parse backend, not something that is programatically set).
Now I'm trying to get the sessionToken from the newly signed up user. Returning the "user" object on success of the signup and inspecting, I don't see a "sessionToken". I also don't see a sessionToken in the user database...
Can somebody give me some code that will return the sessionToken?
Here is the relevant code:
user.signUp(null, {
success: function(user) {
response.success(user);
},
error: function(user, error) {
alert("Error: " + error.code + " " + error.message);
}
});
I don't get a sessionToken here. Where do I get it from?
I think you need to check on your local storage:
Local Storage Report
There are 5 items in local storage, using 0.9KB (0.001MB)
Parse/bqfSO3dVttG65a8CIkC1SdqC0CCqiqYsp1EfsjL8/currentUser
username XXX#gmail.com
email XXX#gmail.com
objectId oVGKr1vdbG
createdAt 2013-03-20T17:17:54.815Z
updatedAt 2013-03-20T17:17:54.815Z
_id oVGKr1vdbG
_sessionToken 12aob7us2lj18pkaddkbvsal7
That is what Parse checks when you do:
var currentUser = Parse.User.current();
var sessionToken = Parse.User.current()._sessionToken;
The code i ended up using looked something like this:
endpoint : "https://api.parse.com/1/login",
parameters : getTheLoginParametersFrom(user),
success : function(response) {
tablesModule.saveSessionId(response.sessionToken);
}
}
Where the result from the "login" is the response.sessionToken.

Resources