How to send Stripe customer ID to Parse - node.js

I've managed to create Stripe customers through Parse using this function:
Parse.Cloud.define("customer", function(request, response){
stripe.customers.create({
email: request.params.useremail
}, function(err, customer) {
if(err){
console.log(err);
response.error(err);
}
else{
console.log(customer);
response.success(customer);
});
});
However, I would like to then be able to send the customer ID that is created to Parse under the current user's data as "cusToken", the same way that "email", "username" and whatnot are stored in the User class.

There are two assumptions that will simplify this code, the first is that the client making the call always does so on behalf of it's logged-in user, not some other user. The second is that stripe create answers a promise. Assuming that:
Parse.Cloud.define("customer", function(request, response) {
var user = request.user;
stripeCreateP({ email: user.email }).then(function(customer) {
user.set("someUserProperty", customer.someStripeProperty); // as an example
return user.save();
}).then(function(result) {
console.log(customer);
response.success(customer);
}, function(err) {
console.log(err);
response.error(err);
});
});
If the stripe api doesn't return a parse Promise, you can "promisify" it as follows...
function stripeCreateP(params) {
var p = new Parse.Promise();
stripe.customers.create(params, function(err, customer) {
if (err) {
p.resolve(customer);
} else {
p.reject(err);
}
});
return p;
}
...and call that with the email param object...
stripeCreateP({ email: user.email }).then( ...
If your app calls this for a user other than the client's logged in user, then you will need to pass user email in request.params as you do in the OP, and furthermore, you'll need to give yourself permission in the code to save a user other than the current one, then you can precede the save with a useMasterKey. See the docs for that.

Related

How to use node.js fetch data from mongodb and push retrieved data into an array?

How to use node.js fetch data from mongodb and push retrieved data into an array ? I have user collection in mongodb and I can fetch the user and its USER_SECRET and PAS_SECRET information by email without problem to display them in a form, but I was failed to push USER_SECRET and PASS_SECRET of user into a users [] array . I Got error 500.
//-----login ui form-----
router.get("/user/login", function (req, res) {
res.render("users/login.ejs");
});
//------ Post ---
router.post("/user_secret", async (req, res) => {
const email = req.body.username;
console.log(email);
users = [];
try {
const user = await User.findOne({ USER_SECRET: email });
if (!user) {
return res.status(404).send("Inputs are Incorrect Information");
}
// res.render("users/addOrEdit", { user });// this works
res.users.push({
username: user.USER_SECRET,
password: user.PASS_SECRET,
});
} catch (e) {
res.status(500).send();
}
});
I could not find the reason of failure. Should I use map method ?
How to check if the users [] has data or not ? Please help.
I think res.users is undefined...so after getting the user, you can write:
res.status(200).send([{
username: user.USER_SECRET,
password: user.PASS_SECRET
}])
Instead of:
res.users.push({ ... })

Post same objectID in to different table

I'm trying to post a data in my user then at the same time, post the _id of my user as a reference id in my donation table.
After I posted my data in the users table like this:
var User = require('../models/user');
var Blooddonation = require('../models/blooddonation');
router.post('/createBlooduser',function(req, res) {
var user = new User();
user.user_lastname = req.body.user_lastname;
user.status= "initial";
user.save(function(err) {});
});
How can I get the _id of the posted data and make a reference id in my donation table? Something like this:
**users.json**
{
_id:ObjectId("5c7e591eee959272cc5768cb"),
user_lastname:"Jhonson",
status:"initial"
}
**blooddonations.json**
{
donor_id:ObjectId("5c7e591eee959272cc5768cb")
}
The _id property is actually created as soon as you create new instance with a statement like new User(). So you can actually access that value before it's even stored in the collection, or at any time after instance creation really:
router.post('/createBlooduser',function(req, res) {
var user = new User();
user.user_lastname = req.body.user_lastname;
user.status= "initial";
user.save(function(err) {
if (err) throw err; // or really handle better
// You can also just create() rather than new Blooddonation({ donor_id: user._id })
Blooddonation.create({ donor_id: user._id }, function(err, donor) {
// check for errors and/or respond
})
});
});
Of if you might just want access to other properties that might "default on save", then you can access in the callback from save() or create():
router.post('/createBlooduser',function(req, res) {
User.create({
user_lastname: req.body.user_lastname;
status: "initial"
}, function(err, user) { // this time we pass from the callback
if (err) throw err; // or really handle better
Blooddonation.create({ donor_id: user._id }, function(err, donor) {
// check for errors and/or respond
});
});
});

nodejs passport - use same routes in api but return different sets of data based on permissions

Not sure of a clean way to go about his. Let's say I have this endpoint:
GET /api/Books/
For the user on the webservice, this will return only the user's resources. It might look a little something like this:
exports.getBooks = function(req, res) {
// find all books for user
BookModel.find({ userId: req.user._id }, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
};
The web service using the api needs the user to be logged in first. I can achieve this using a basic passport strategy to ensure authentication. But let's say I have an admin account that needs to see ALL books ever recorded. What's more is that the admin account and user accounts have completely different properties so assigning a Boolean for permissions is not enough. Using the same endpoint:
GET /api/Books
I see no reason to write another endpoint to achieve this. However the difference would look like this:
exports.getBooks = function(req, res) {
// find all books in the database
BookModel.find({}, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
};
However I cannot come up with a clean way to achieve this while also using the passport middlewear as it is intended like so:
router.route('/books')
.post(authController.isAuthenticated, bookController.postBooks)
.get(authController.isAuthenticated, bookController.getBooks);
The function isAuthenticated will will only verify whether or not the user requesting resources has permission and does not change the way the controller behaves. I'm open to ideas.
ANSWER
The user #ZeroCho suggested to check user properties in req.user object to determine what should be sent back. This was more simple than I expected. In my implementation for passport.BasicAuth strategy, I check which table has a matching doc. Once the user is found in the common user or Admin user table all you do is add a property in the isMatch return object.
// Basic strategy for users
passport.use('basic', new BasicStrategy(
function(email, password, done) {
verifyUserPassword(email, password,
function(err, isMatch) {
if(err) { return done(err); }
// Password did not match
if(!isMatch) { return done(null, false); }
// Success
var userInfo = {
email: email,
isAdmin: isMatch.isAdmin || false,
businessID: isMatch.businessID || false
};
return done(null, userInfo);
});
})
);
Then you can check if .isAdmin or .businessID is valid in your requests.
Just separate your controller by if statement
exports.getBooks = function(req, res) {
if (req.user.isAdmin) { // or some other code to check user is admin
// find all books in the database
BookModel.find({}, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
} else {
BookModel.find({ userId: req.user._id }, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
}
};

Why is my Node validation failing in this POST?

I'm following along in the MEAN machine Node authentication tutorial.
Here is their source code: https://github.com/scotch-io/mean-machine-code/blob/master/10-node-authentication/server.js I basically have everything except for the apiRouter.post('/authenticate', part
The Express APIs are working:
http://localhost:8615/api/users will return a list of users from scotch.io's MongoDB
The following is the API for /api/users:
apiRouter.route('/users')
// create a user (accessed at POST http://localhost:8615/api/users)
.post(function(req, res) {
// create a new instance of the User model
var user = new User();
// set the users information (comes from the request)
user.name = req.body.name;
user.username = req.body.username;
user.password = req.body.password;
// save the user and check for errors
user.save(function(err) {
if (err) {
// duplicate entry
if (err.code == 11000)
return res.json({ success: false, message: 'A user with that username already exists. '});
else
return res.send(err);
}
// return a message
res.json({ message: 'User created!' });
});
})
// get all users (access at GET http://localhost:8615/api/users)
.get(function(req, res) {
User.find(function(err, users) {
if (err) return res.send(err);
// return the users
res.json(users);
})
});
Here is my user.js User Schema
// SCHEMAS ------------------------------------
// user schema
var UserSchema = new Schema({
name: String,
username: { type: String, required: true, index: { unique: true }},
password: { type: String, required: true, select: false }
// ^ select false will not return passwords
});
// hash the password before the user is saved
UserSchema.pre('save', function(next) {
var user = this;
// PUT username
if (!user.isModified('username')) return next();
// PUT name
if (!user.isModified('name')) return next();
// hash the password only if the password has been changed or user is new
if (!user.isModifited('password')) return next();
// generate the salt
bcrypt.hash(user.password, null, null, function(err, hash) {
if (err) return next(err);
// change the password to the hashed version
user.password = hash;
next();
});
});
FROM THE BOOK:
Create a Sample User
First, we need to make sure that we even have a user to authenticate
since towards the end of last chapter, we deleted everyone. Let’s
create the user using the POST http://localhost:8080/api/users route
we created in our API to add a user to our database.
We will send a POST request with the following information: Name Chris
Username chris Password supersecret
I'm using Postman to add a new user, as you can see I have put in key/value pairs for username and password, however getting an error saying "Validation failed" "username is required" "password is required":
UPDATE, I just tried x-www-form-urlencoded and got the following error
GET /api/users 200 66.141 ms - 655
••• API CRUD hit •••
/Users/leongaban/NodeDallas/projects/awesome-test/app/models/user.js:27
if (!user.isModifited('password')) return next();
^
TypeError: Object { password: 'supersecret',
username: 'Chris',
name: 'chris',
_id: 54c001dc4ee4028c18e61334 } has no method 'isModifited'
at model.UserSchema.methods.comparePassword.user (/Users/leongaban/NodeDallas/projects/awesome-test/app/models/user.js:27:12)
Screenshot of error in Postman: https://s3.amazonaws.com/f.cl.ly/items/1M0M392M0E3b2i430I1n/Image%202015-01-21%20at%201.45.51%20PM.png
try x-www-form-urlencoded in postman, that would do.
You want to push a json to your server. Select raw and set the data type to JSON.
Then you just have to write your user in JSON format with all his fields here.
{
"name": "Chris",
"username": "chris",
"password": "supersecret"
}

Pre-populating documents using Mongoose + Express

I am new to Node+Mongoose, and am currently in the process of creating an API using KeystoneJS. I've managed to populate all posts with the author's email and name. My question is, is there a way to populate the post with author everytime, possibly with some middlewear, without having to rewrite it in each method where I retrieve posts? My goal is to not have multiple instances of populate('author', 'email name') scattered throughout the code. For instance, in the future, I'd like to include the author's profile photo url as well, and I'd prefer to be able to make that change in a single place, that will then be reflected in every place that I retrieve posts.
Current implementation:
Post.model.find().populate('author', 'email name').exec(function (err, posts) {
if (!err) {
return res.json(posts);
} else {
return res.status(500).send("Error:<br><br>" + JSON.stringify(err));
}
});
Post.model.findById(req.params.id).populate('author', 'email name').exec(function (err, post) {
if(!err) {
if (post) {
return res.json(post);
} else {
return res.json({ error: 'Not found' });
}
} else {
return res.status(500).send("Error:<br><br>" + JSON.stringify(err));
}
});
You can create model using statics. This is example of methods for schema
PostSchema.statics = {
getAll: function(cb) {
return this
.find()
.populate('author', 'email name')
.exec(cb);
}
}
You still should use "populate", but it will be in schema file, so you will not care about it in future

Resources