Parse.com: Signup user to role - javascript

How do you add a user to an existing role when they're signing up? My code below doesn't work, I don't get any errors or any prints in the logs (not sure what I'm doing wrong):
Parse.User.signUp(req.body.email, req.body.password, {
"name": req.body.name,
"email": req.body.email,
}, {
success: function(user) {
var query = new Parse.Query(Parse.Role);
query.equalTo("name", 'Basic User');
query.find({
success: function(roles) {
alert("HELLO" + roles);
if (roles.length < 1) {
alert("HELLO");
console.log("Error Signing Up: No roles for " + signUpRoleGroup + " were found");
} else {
alert("HERE");
roles[0].getUsers().add(user);
roles[0].save();
}
},
error: function(error) {
alert("Could not add users to the account " + accountName + " error: " + error.message);
}
});
},
error: function(user, error) {
alert("Error signing up user");
}
});

I think what's going on is the caller isn't giving this function a chance to finish saving the role. The cloud function should wait until the role is saved before invoking response.success() or error().
Here's a promise-returning rewrite of the same code. Easier on the eyes, I think, and clearer about asynch tasks done serially. This puts you in more firm control of the response.
Parse.Cloud.define("signupAsBasicUser", function(request, response) {
signupAsBasicUser(request.params.name, request.params.password, request.params.email).then(function(user) {
response.success(user);
}, function(error) {
response.error(error);
});
});
// return a promise fulfilled with a signed-up user who is added to the 'Basic User" role
//
function signupAsBasicUser(name, password, email) {
Parse.Cloud.useMasterKey();
var user = new Parse.User();
user.set("username", name);
user.set("password", password);
user.set("email", email);
return user.signUp().then(function() {
var query = new Parse.Query(Parse.Role);
query.equalTo("name", 'Basic User');
return query.find();
}).then(function(roles) {
if (roles.length < 1) return Parse.Promise.error("no such role");
roles[0].getUsers().add(user);
return roles[0].save();
}).then(function() {
return user;
});
}

Related

Socket.IO - Callback to user who emited only

I am making a chat application which requires users to log in, I have so far managed to get the login system working by using UserApp.io, but I cant seem to find a way which would send a "Callback" back to the user who has emited the information to the server.
So for index.html, when a login form is submitted, it would gather the values of the two fields and emit the data to the backend.
$('form#login').submit(function() {
var data = {};
data.email = $("#login_email").val();
data.password = $("#login_password").val();
socket.emit('user login', data);
});
In the index.js file, it receives the details and checks using the UserApp API that the user is valid and all the details are correct. It also retrieves information like the first and last name.
socket.on('user login', function (user) {
logger.info('Receiving login info for "' + user.email + '"...');
UserApp.User.login({"login": user.email, "password": user.password}, function (error, result) {
if (error) {
logger.error('Login failed: ' + error.message);
} else {
var userToken = result.token;
var userID = result.user_id;
console.log("User has logged in.");
UserApp.User.get({
"user_id": userID
}, function (error, result) {
if (error) {
logger.error(error.message);
} else {
logger.info(result[0]['first_name'] + " " + result[0]['last_name'] + " Has logged in!")
}
});
}
});
});
So here is my issue. I cant seem to find a way of giving a callback to index.html so it can show errors like "Incorrect username".
So is there a way of giving a callback to one person, more specificly, the person who submitted the login form?
Any help would be appreciated.
Thanks.
socket.io has acknowledgement callbacks, here are the docs
http://socket.io/docs/#sending-and-getting-data-(acknowledgements)
Add a callback function as the third argument when emitting
$('form#login').submit(function() {
var data = {};
data.email = $("#login_email").val();
data.password = $("#login_password").val();
socket.emit('user login', data, function (result) {
console.log(result);
});
});
and then the callback function server side can have an additional parameter which is the callback you defined when emitting
socket.on('user login', function (user, callback) {
logger.info('Receiving login info for "' + user.email + '"...');
UserApp.User.login({"login": user.email, "password": user.password}, function (error, result) {
if (error) {
logger.error('Login failed: ' + error.message);
} else {
var userToken = result.token;
var userID = result.user_id;
console.log("User has logged in.");
UserApp.User.get({
"user_id": userID
}, function (error, result) {
if (error) {
logger.error(error.message);
} else {
logger.info(result[0]['first_name'] + " " + result[0]['last_name'] + " Has logged in!")
return callback('your results');
}
});
}
});
});

parse-server js can't login user, even though registration goes through and logs user in

I'm currently building a parse-server app with vuejs + vuex on the front end.
I am able to register an account(and once registered the user is logged in) with this code:
REGISTER_USER (state, username, email, password) {
var user = new Parse.User()
user.set('username', username)
user.set('password', password)
user.set('email', email)
user.signUp(null, {
success: function (user) {
state.currentUser = user
},
error: function (user, error) {
state.registerError = error
}
})
}
but if I log the user out and try to log them in with:
LOGIN_USER (state, email, password) {
Parse.User.logIn(email, password, {
success: function (user) {
state.currentUser = user
},
error: function (user, error) {
state.loginError = error
console.log('error logging in: ' + JSON.stringify(error) + ' userobject: ' + JSON.stringify(user))
console.log('current user: ' + JSON.stringify(Parse.User.current()))
}
})
}
I get {"code":101,"error":"Invalid username/password."}
I've confirmed that the proper username and password is reaching the function, but then it goes south somehow. any help would be greatly appreciated.
Finally figured it out. There are 2 available methods for login, tried the other one and worked perfectly
https://parse.com/docs/js/api/classes/Parse.User.html#methods_logIn
var user = new Parse.User()
user.set('username', username)
user.set('password', password)
user.logIn({
success: function (user) {
this.username = ''
this.password = ''
dispatch('SET_CURRENT_USER', user)
},
error: function (user, error) {
// console.log('login errors: ' + JSON.stringify(error) + 'for user: ' + JSON.stringify(user))
// state.loginErrors = error
}
})

Adding Users to Parse Role in Cloud Code

I want to add users to my Parse.Role but it's not working. I looked at a number of examples and they all seem pretty straight-forward however I'm unable to get it right. Here is my code:
Parse.Cloud.define("activateVendor", function(request, response){
var query = new Parse.Query(Parse.Role);
query.equalTo("name", "vendor");
query.first ({
success: function(role) {
role.getUsers().add(request.params);//request.params is the parse object, should I be using request.params.id?
role.save();
},
error: function(error) {
throw "Got an error " + error.code + " : " + error.message;
}
})
});
It depends on who you wish added to the role. The user who made the cloud request is available via the request object...
role.getUsers().add(request.user);
Otherwise, you can get a user via a query as #RobertRowntree suggests. (though, I'd suggest doing it with promises).
does what you want with 2 queries (Role, User) ...
var qu = new Parse.Query(Parse.User);
var qr = new Parse.Query(Parse.Role);
Parse.Cloud.useMasterKey();
qr.get(roleId, {
success: function(role) {
_role = role;
qu.get(userId, {
success: function(user) {
_role.getACL().setRoleReadAccess(_role, true);
_role.getUsers().add(user);
_role.save();
response.success(_role.toJSON());
},
error: function(object, error) {
}
});
},
error: function(object, error) {
}
});

Retrieve customer email from ID contained in webhook in Parse.com

I have an App using Parse.com as a backend and an external site that acts as my payment gateway. Upon receiving the customer/subscription webhook data from Stripe I wish to lookup the users email so I can then run a Cloud Code function and change their user status to 'paid'
My webhook receiver is:
Parse.Cloud.define("update_user", function(request, response) {
var data = request.params["data"]
var customer = data.object.customer;
response.success'Working' + request);
});
And I am able to get an email back from stripe from the customer ID using:
Parse.Cloud.define("pay", function(request, response) {
Stripe.initialize(STRIPE_SECRET_KEY);
console.log(JSON.stringify(request.params));
Stripe.Customers.retrieve(
customerId, {
success:function(results) {
console.log(results["email"]);
// alert(results["email"]);
response.success(results);
},
error:function(error) {
response.error("Error:" +error);
}
}
);
});
I need help turning this into a complete function that is run on receipt of every webhook from Stripe. I am also struggling with options for fallback if this does not work for whatever reason.
EDIT
Taking parts of the first answer and I now have:
Parse.Cloud.define("update_user", function(request, response) {
Stripe.initialize(STRIPE_SECRET_KEY);
var data = request.params["data"]
var customerId = data.object.customer;
get_stripe_customer(customerId, 100).then(function(stripeResponse) {
response.success(stripeResponse);
}, function(error) {
response.error(error);
});
});
function get_stripe_customer (customerId) {
Stripe.initialize(STRIPE_SECRET_KEY);
return Stripe.Customers.retrieve(
customerId, {
success:function(results) {
console.log(results["email"]);
},
error:function(error) {
}
}
);
};
My knowledge is really falling down on the Promise side of things and also the callback (success:, error, request response) etc further reading would be appreciated.
This is now working
Out of interest I did this:
Parse.Cloud.define("update_user", function(request, response) {
var data = request.params["data"]
var customerId = data.object.customer;
get_stripe_customer(customerId, 100).then(function(stripeResponse) {
return set_user_status(username, stripeResponse);
}).then(function(username) {
response.success(username);
}, function(error) {
response.error(error);
});
});
function get_stripe_customer (customerId) {
Stripe.initialize(STRIPE_SECRET_KEY);
return Stripe.Customers.retrieve(
customerId, {
success:function(results) {
// console.log(results["email"]);
},
error:function(error) {
}
}
);
};
function set_user_status(stripeResponse) {
Parse.Cloud.useMasterKey();
var emailquery = new Parse.Query(Parse.User);
emailquery.equalTo("username", stripeResponse['email']); // find all the women
return emailquery.first({
success: function(results) {
alert('running set_user_status success');
var user = results;
user.set("tier", "paid");
user.save();
},
error:function(error) {
console.log('error finding user');
}
});
};
open to improvements...
EDIT - I (#danh) cleaned it up a bit. A few notes:
used promises throughout. much easier to read and handle errors
get_stripe_customer requires only one param (that 100 was my idea to charge $100)
set_user_status appears to need only user email as param, which apparently is in the stripeResponse
set_user_status returns a promise to save the user. that will be fulfilled with the user object, not the username
be sure you're clear on how to identify the user. stripe apparently provides email address, but in your user query (in set_user_status) you compare email to "username". some systems set username == email. make sure yours does or change that query.
Parse.Cloud.define("update_user", function(request, response) {
var data = request.params["data"]
var customerId = data.object.customer;
get_stripe_customer(customerId).then(function(stripeResponse) {
var email = stripeResponse.email;
return set_user_status(email);
}).then(function(user) {
response.success(user);
}, function(error) {
response.error(error);
});
});
function get_stripe_customer(customerId) {
Stripe.initialize(STRIPE_SECRET_KEY);
return Stripe.Customers.retrieve(customerId).then(function(results) {
// console.log(results["email"]);
return results;
});
};
function set_user_status(email) {
Parse.Cloud.useMasterKey();
var emailquery = new Parse.Query(Parse.User);
emailquery.equalTo("username", email); // find all the women
return emailquery.first().then(function(user) {
user.set("tier", "paid");
return user.save();
}, function(error) {
console.log('error finding user ' + error.message);
return error;
});
}
Did a quick skim of the docs pertaining to stripe, and it looks like the steps are: (1) make a stripe REST-api call from your client side to get a token, (2) pass that token to a cloud function, (3) call stripe from the parse cloud to finish paying. I understand that you'd like to include a (4) fourth step wherein the transaction is recorded in the data for the paying user.
From the client (assuming a JS client):
var token = // we've retrieved this from Stripe's REST api
Parse.Cloud.run("pay", { stripeToken: token }).then(function(result) {
// success
}, function(error) {
// error
});
On the server:
Parse.Cloud.define("pay", function(request, response) {
var user = request.user;
var stripeToken = request.params.stripeToken;
payStripeWithToken(stripeToken, 100).then(function(stripeResponse) {
return updateUserWithStripeResult(user, stripeResponse);
}).then(function(user) {
response.success(user);
}, function(error) {
response.error(error);
});
});
Now we need only to build promise-returning functions called payStripeWithToken and updateUserWithStripeResult.
// return a promise to pay stripe per their api
function payStripeWithToken(stripeToken, dollarAmt) {
Stripe.initialize(STRIPE_SECRET_KEY); // didn't see this in the docs, borrowed from your code
return Stripe.Charges.create({
amount: dollarAmt * 10, // expressed in cents
currency: "usd",
card: stripeToken //the token id should be sent from the client
});
// caller does the success/error handling
}
// return a promise to update user with stripeResponse
function updateUserWithStripeResult(user, stripeResponse) {
var transactionId = // dig this out of the stripeResponse if you need it
user.set("paid", true);
user.set("transactionId", transactionId);
return user.save();
}

XMLHttpRequestError issue when signing up user using parse

I'm trying to use Parse.com to sign users up to my application I'm developing. However I seem to get an error when firing my function.
Parse.initialize("APP ID", "JS KEY");
function signUp() {
var user = new Parse.User();
// Get user inputs from form.
var username = document.login.username.value;
var password = document.login.password.value;
user.set("username", username);
user.set("password", password);
user.signUp(null, {
success: function (user) {
// Hooray! Let them use the app now.
alert("Success");
},
error: function (user, error) {
// Show the error message somewhere and let the user try again.
alert("Error: " + error.code + " " + error.message);
}
});
};
The error:
Error: 100 XMLHttpRequest failed: {"statusText":"","status":0,"response":"","responseType":"","responseXML":null,"responseText":"","upload":{"ontimeout":null,"onprogress":null,"onloadstart":null,"onloadend":null,"onload":null,"onerror":null,"onabort":null},"withCredentials":false,"readyState":4,"timeout":0,"ontimeout":null,"onprogress":null,"onloadstart":null,"onloadend":null,"onload":null,"onerror":null,"onabort":null}
Any help here would be great, i'm unsure what's causing the error. Seems to work correctly when i'm not passing form data through it. Thanks.
I think you instead should use:
user.setUsername(username);
user.setPassword(password);
Also, these can be combined:
Parse.User.signUp(username, password, { ACL: new Parse.ACL() }, {
success: function (user) {
// Hooray! Let them use the app now.
alert("Success");
},
error: function (user, error) {
// Show the error message somewhere and let the user try again.
alert("Error: " + error.code + " " + error.message);
}
});

Categories