If a user is registered by calling the following call once:
private void signup() {
ParseUser user = new ParseUser();
user.setUsername("ola");
user.setPassword("kari4ever");
user.setEmail("ola#nordmann.no");
user.put("phone", "650-253-0000");
user.signUpInBackground(new SignUpCallback() {
public void done(ParseException e) {
if (e == null) {
toast("Hooray! The user is signed up");
} else {
toast("signup failed \n" + e.toString());
}
}
});
}
If the user already exists, the parse library repeats the HTTP request many times before the SingupCallback.done() method is called.
Is this a bug?
Related
I am trying to build an android application using parse to store user data.
In the user table, I am storing username password, status, and a profile picture.
I am trying to create a signup page, and to do that I am using file.saveInBackground to upload the image file and then user.signUpInBackground to sign up the user.
It is working fine, but every time a user sign's up it makes multiple requests (around 30).
Is there any particular reason why this is happening?
private void addUser(String username, String role, String password) {
final ParseFile file = new ParseFile(photoFile);
file.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
User user = new User();
user.setUsername(username);
user.setRole(role);
user.setPassword(password);
user.setProfileImage(file);
user.signUpInBackground(new SignUpCallback() {
#Override
public void done(ParseException e) {
if (e != null) {
Toast.makeText(getContext(), "Error while signing up!", Toast.LENGTH_SHORT).show();
}
goMainActivity();
}
});
}
}
});
}
Welcome all!
I am currently working to pass a token generated by Stripes API from an Android app to a ParseServer. Below is my code, please be advised that I commented out previous failed attempts to let you know what I have tried and to also spark your imagination. Please note that with trial and error the issue presents to be with saving the data to the server. I have double checked that the class User has write permissions and it has an Object attribute titled token.
// Test the data.
if (userCard.validateCard()) {
Stripe stripe = new Stripe(CardActivity.this, "correct data is here I removed it, for StackOverflow");
stripe.createToken(
userCard,
new TokenCallback() {
public void onSuccess(final Token token) {
// Send token to your server
// Query the users, and get the username.
ParseQuery<ParseObject> query = ParseQuery.getQuery("User");
ParseUser user = ParseUser.getCurrentUser();
String objectId = user.getObjectId();
// Query the current user.
//query.whereEqualTo("objectId", username);
ParseObject object;
try {
object = query.get(objectId);
object.put("token", token);
object.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Toast.makeText(CardActivity.this, "Success", Toast.LENGTH_SHORT).show();
}
}
});
} catch (ParseException e) {
Toast.makeText(CardActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
// Attempt to update... Currently not working.
/*query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null && objects != null) {
for (ParseObject object : objects) {
object.put("token", token);
object.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Toast.makeText(CardActivity.this, "Success", Toast.LENGTH_SHORT).show();
}
}
});
}
} else {
Toast.makeText(CardActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});*/
}
public void onError(Exception error) {
// Show error message
Toast.makeText(CardActivity.this,
error.getMessage(),
Toast.LENGTH_LONG
).show();
}
}
);
} else {
Toast.makeText(CardActivity.this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
A few things here:
1) Parse allows you to add/overwrite information to objects from their "shell". This is a ParseObject instance, set to a specified class, assigned an objectId, and then whatever values you want to add/change, and then saved. Any field you did not assign a value to will be ignored, so say you only set field3, field2 and field1 will not be overwritten to nothing.
2) ParseUser user = ParseUser.getCurrentUser() already returns a user object. You don't even need to create a shell from the id, this is a fully functioning parse object. You can then set the value you want and save it!
3) Queries and fetches (and cloud function calls) are asynchronous. This means that the code executes over time on a background thread, and your main thread will go on. So, things that require the results of these methods need to be called within the completion handler. You're doing object = query.get(objectId), but query.get() takes a bit to run so you're probably running through the rest of the code block before object has a proper value.
4) To my knowledge (not an Android developer, but I've used the JS and iOS SDKs) the Parse SDKs have a specific query for the User class that is a bit easier and safer to use than creating a ParseQuery set to the "User" class. Should be something like ParseUser.query()
So, not being an Android developer, I think what you want is more like this:
// Test the data.
if (userCard.validateCard()) {
Stripe stripe = new Stripe(CardActivity.this, "correct data is here I removed it, for StackOverflow");
stripe.createToken(
userCard,
new TokenCallback() {
public void onSuccess(final Token token) {
// Send token to your server
// Query the users, and get the username.
ParseQuery<ParseObject> query = ParseQuery.getQuery("User");
ParseUser user = ParseUser.getCurrentUser();
try {
user.put("token", token);
user.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Toast.makeText(CardActivity.this, "Success", Toast.LENGTH_SHORT).show();
}
}
});
} catch (ParseException e) {
Toast.makeText(CardActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
public void onError(Exception error) {
// Show error message
Toast.makeText(CardActivity.this,
error.getMessage(),
Toast.LENGTH_LONG
).show();
}
}
);
} else {
Toast.makeText(CardActivity.this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
I am working on an application using Parse.com as backend support.I have used ParseUser for login and signup ,but now I have to implement change Password and forgot password ,but don't know how to implement it..Please help me to implement this functionalities.
The code which I have used to login the ParseUser is as follows:
ParseUser.logInInBackground(str_email2, str_password2, new LogInCallback() {
#Override
public void done(ParseUser user, ParseException e) {
dlg.dismiss();
if(e == null)
{
Log.d(">>>","ObjId>>"+user.getObjectId()+" Username>>>"+user.getUsername());
}
else
loginUnSuccessful();
}
});
To request a new password (in case the user forgot it) you can use this:
ParseUser.requestPasswordResetInBackground("myemail#example.com",
new RequestPasswordResetCallback() {
public void done(ParseException e) {
if (e == null) {
// An email was successfully sent with reset instructions.
} else {
// Something went wrong. Look at the ParseException to see what's up.
}
}
});
And to change a password you can just get the current user and do the following:
ParseUser currentUser = ParseUser.getCurrentUser();
currentUser.setPassword("new_password");
currentUser.saveInBackground();
In the doc, you have this sample code:
ParseUser.requestPasswordResetInBackground("myemail#example.com",
new RequestPasswordResetCallback() {
public void done(ParseException e) {
if (e == null) {
// An email was successfully sent with reset instructions.
} else {
// Something went wrong. Look at the ParseException to see what's up.
}
}
});
Source: https://parse.com/docs/android_guide#users-resetting
You can not reset the password for not signed (anonymous) ParseUser.
If you are using email feature for ParseUser, you can send password reset mail like this
ParseUser.requestPasswordResetInBackground(
stringEmail,
new RequestPasswordResetCallback() {
public void done(ParseException e) {
...
}
}
);
If you are not using email feature, you need to write a cloud method in your main.js file, like this
Parse.Cloud.define("resetPassword", function (request, response) {
Parse.Cloud.useMasterKey(); /*important*/
var username = request.params.username;
var password = request.params.password;
var objUser = Parse.Object.extend("User");
var qUser = new Parse.Query(objUser);
qUser.equalTo("username", username);
qUser.find().then(function (resultObj) {
if(resultObj.length > 0){
var userObj = resultObj[0];
userObj.set("password", password);
return userObj.save();
} else {
response.error("User does not exist");
}
}).then(function () {
response.success("Password RESET DONE SUCCESSFULLY");
}, function (error) {
response.error("Error " + error);
});
});
and call that method from your app, like this
Map<String, Object> params = new HashMap<String, Object>();
params.put("password", password);
params.put("username", username);
ParseCloud.callFunctionInBackground("resetPassword", params, new FunctionCallback<String>() {
#Override
public void done(String response, ParseException e) {
if (e == null) {
...
} else {
..
}
}
});
This way you can reset user password using username or mobile number.
I've implemented a Parse & Facebook flow in my Android app using ParseFacebookUtils.
TL;DR
Created a Parse user after logging in (and linking) with Facebook
(ParseFacebookUtils.logIn)
Logged out (ParseFacebookUtils.logOut &
ParseUser.logOut)
Logging in again with Facebook creates a new Parse
user instead of fetching the old one.
Longer version: The login flow works - the ParseFacebookUtils.logIn call launches the Facebook dialog and after accepting a new Parse user is being created and linked to the user's Facebook account.
The problems arises after logging out (ParseFacebookUtils.logOut and ParseUser.logOut), and trying to log back in to the same Parse user. The Facebook dialog shows up briefly then I'm getting redirected to the app (as it's already authorized for that Facebook user), but it seems like a new Parse user is being created instead of finding the previous one for the relevant Facebook user.
Question: Is there a way to enable such flow? Would I have to get the already created user manually?
The code for my MainActivity, in which all the login logic reside:
public class MainActivity extends Activity {
private ProgressBar progressBar;
private Button loginButton;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.splash_loading_spinner);
loginButton = (Button) findViewById(R.id.splash_facebook_login);
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onLoginButtonClicked();
}
});
ParseAnalytics.trackAppOpened(getIntent());
// Check if there is a currently logged in user
// and they are linked to a Facebook account.
ParseUser currentUser = ParseUser.getCurrentUser();
if ((currentUser != null) && ParseFacebookUtils.isLinked(currentUser)) {
// load data from Parse user and launch the next activity immediately
retrieveData();
} else {
failedLoggingIn();
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
ParseFacebookUtils.getSession().onActivityResult(this, requestCode, resultCode, data);
}
// this method will link the current ParseUser to the used Facebook account if needed
private boolean linkFacebookUser() {
ParseUser user = ParseUser.getCurrentUser();
// save fb_id and email to the parse user
Request.newMeRequest(ParseFacebookUtils.getSession(), new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser fbUser, Response response) {
if (fbUser == null) {
Log.e("Facebook Me Request", "Failed fetching user Facebook Graph object.");
} else {
Log.d("Facebook Me Request", "Received Facebook graph object for "+fbUser.getId()+"("+fbUser.getProperty("email").toString()+")");
ParseUser.getCurrentUser().put("fb_id", fbUser.getId());
ParseUser.getCurrentUser().setEmail(fbUser.getProperty("email").toString());
ParseUser.getCurrentUser().setUsername(fbUser.getProperty("email").toString());
ParseUser.getCurrentUser().setPassword(UUID.randomUUID().toString());
ParseUser.getCurrentUser().signUpInBackground(new SignUpCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.d("Parse signup user", "Successfully saved a new Parse-Facebook user!");
retrieveData();
} else {
Log.e("Parse signup user", "FAILED saving a new Parse-Facebook user. Error: " + e.getMessage());
e.printStackTrace();
}
}
});
}
}
}).executeAsync();
return true;
}
private void retrieveData() {
// fetch data needed to show movie recommendations
Log.d("Parse Facebook Login Info", "fb_id=" + ParseUser.getCurrentUser().get("fb_id"));
startActivity(new Intent(this, BrowseMoviesActivity.class));
finish();
}
private void failedLoggingIn() {
ParseUser.logOut();
progressBar.setVisibility(View.GONE);
loginButton.setVisibility(View.VISIBLE);
}
private void onLoginButtonClicked() {
Log.d("UI", "Clicked the Facebook login button");
progressBar.setVisibility(View.VISIBLE);
loginButton.setVisibility(View.GONE);
List<String> permissions = Arrays.asList(
"public_profile",
"user_friends",
"user_actions.video",
ParseFacebookUtils.Permissions.User.EMAIL,
ParseFacebookUtils.Permissions.User.ABOUT_ME,
ParseFacebookUtils.Permissions.User.RELATIONSHIPS,
ParseFacebookUtils.Permissions.User.BIRTHDAY,
ParseFacebookUtils.Permissions.User.LOCATION
);
ParseFacebookUtils.logIn(permissions, this, new LogInCallback() {
#Override
public void done(ParseUser user, ParseException err) {
MainActivity.this.progressBar.setVisibility(View.GONE);
if (user == null) {
Log.d("ParseFacebookLogin", "Uh oh. The user cancelled the Facebook login.");
if (err != null) {
Log.d("ParseFacebookLogin", "Error: " + err.getLocalizedMessage());
}
failedLoggingIn();
} else if (user.isNew()) {
Log.d("ParseFacebookLogin", "User signed up and logged in through Facebook!");
// we should probably use this scenario to set fb id to the Parse user
linkFacebookUser();
} else {
Log.d("ParseFacebookLogin", "User logged in through Facebook!");
if (user.get("fb_id") == null) {
linkFacebookUser();
} else {
retrieveData();
}
}
}
});
}
}
I had the same problem. Actually it was a bug in parse sdk and the problem was solved without changing any of my code, just by installing the latest parse android sdk(1.8.1 at the time of writing).
I want a unique user but I don't need it to be a formal thing for my app. So, on launch I inspect shared preferences for a previously stored username. I handle the user creation or login like so:
String parseUsername = _appPrefs.getParseUsername();
_progress.setVisibility(View.VISIBLE);
if (parseUsername == null) {
Log.v(TAG, "Creating a user.");
ParseUser.enableAutomaticUser();
_user = ParseUser.getCurrentUser();
_user.setPassword("abc123");
_user.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.w(TAG, String.format("User '%s' created.", _user.getUsername()));
_progress.setVisibility(View.GONE);
_appPrefs.saveParseUsername(_user.getUsername());
createStory();
return;
}
Log.e(TAG, "Error creating user: ", e);
}
});
} else {
Log.v(TAG, String.format("Logging the user '%s' in with password '%s'.", parseUsername, "abc123"));
ParseUser.logInInBackground(parseUsername, "abc123", new LogInCallback() {
#Override
public void done(ParseUser user, ParseException e) {
Log.v(TAG, "User logged in.");
_progress.setVisibility(View.GONE);
if (e == null) {
createStory();
return;
}
Log.e(TAG, "Error logging in: ", e);
}
});
}
I can see the user being successfully created in the logs. I can kill the app and re-launch but it always fails with "invalid login credentials" response from Parse.
If I manually enter abc123 in the Parse data browser then everything works. Ideas?