I am letting the user change his credentials.
He types new username, email and password and I go like:
ParseUser user = ParseUser.getCurrentUser(); user.setUsername("MY NEW NAME"); user.setEmail(email); user.setPassword("MY NEW PW"); user.saveInBackground(...);
So what? So this
save() call might fail, for a big number of reasons (example: username already taken by someone else). I can tell that in this case none of the above fields gets updated, which is fair: I show an error, user knows that all went wrong.
Things get complicated if you notice that, even after the
user above keeps its dirty fields, which couldn’t be saved to the server. I.e.
//saveInBackground fails //... user.getUsername().equals("MY NEW NAME") // true!
Now, I am able to get these fields back to the right values by calling
user.fetch(), but this doesn’t work with the
This is particularly unwanted, because any future call to
save() or such (which might not fail because maybe it’s a completely different call) will update the password too! I.e.
//later ParseUser user = ParseUser.getCurrentUser(); user.put("stuff"); user.save();
This won’t only put “stuff”, but also change the password to “MY NEW PW”.. without the user ever knowing.
Is there any way to reset the local
password field, other than
fetch() which doesn’t work? I know I could save username, email and password with three different queries but that is not a possible solution for my case.
A workaround could be to use
on PFUser class (with PFUser.currentUser().sessionToken as token) when save fails, but that is still a risk for becomeInBackground to fail.
It could at least prevent some cases to happend if becomeInBackground effectively undoes setPassword, and accepts current sessionToken as parameter, I haven’t tested that
Looking at the newest release I’ve read in the changelog:
V1.10.2 — SEPTEMBER 15, 2015
New: Added ParseObject.revert() and revert(key) to allow reverting
Looks like this could be it. It was definitely needed.
If it was my problem I would try to create an oldUser first and save all current data to it, then when failing, it would be time to change every thing back to normal value, or if success it is time to kill oldUser. Hope it may help.
The password plain text is not stored in Parse and as such it cannot be obtained by your app. Found it here https://www.parse.com/questions/get-current-users-password-to-compare-it-with-a-string
If you want to change password you can use
ParseUser.requestPasswordResetInBackground() so you will change the password with the help of email.
But if you need to get password really hard, you can store it in the
SharedPreferences after the login.
After some test and check, here are some conclusion.
- In parse, “password” is a special field, you cannot access it by ParseUser, That is way ParseUser have setPassword() but haven’t getPassword() method
- Even in back-stage management [Core] – [Data] – [User], you can see “password” field is Hidden
- That is why fetch() method cannot recover original “password” value
So, I think if want implements above you need, try this way
// First time register // ParseUser user = ParseUser.getCurrentUser(); user.setUsername("MY NAME"); user.setEmail(email); user.setPassword("MY PW"); user.put("_password", "MY PW"); // The key can't use "password", this's reserve key word in Parse // user.saveInBackground(...); // Next time update // user.setUsername("MY NEW NAME"); user.setPassword("MY NEW PW"); user.saveInBackground(...); // if have something exception // user.fetch(); // user.setPassword(user.get("_password")); user.save(); ParseUser.login("MY NAME", "MY PW"); // Error ParseUser.login("MY NAME", "MY NEW PW"); // Ok user.fetch(); user.setPassword(user.get("_password")); user.save(); ParseUser.login("MY NAME", "MY PW"); // OK