I have a controller function that is declared like this. Based on my comment for this function, I need to call a DB method to get the currentUser data, but I want to re-use an exports.function for that.
I want to call this getme function:
// Get the profile of the current user through JWT.
exports.getme = (req, res) => {
db.User.findOne({
where: { id: req.user.id },
include: [
{
model: db.Role,
as: "role"
},
{
model: db.UserType,
as: "userType"
},
{
model: db.PushToken,
as: "pushToken"
},
{
model: db.StripeAccount,
as: "stripeAccount"
}
],
attributes: defaultAttributes
})
.then(data => {
res.send(data)
})
.catch(err => {
console.log(err)
res.status(500).send({
message: "An error has occured while retrieving data."
})
})
}
from this createStripeAccount function.
// Create Stripe Account
// If there's no stripeAccount connected to the current user,
// only then will we attempt to call stripe's create.
exports.createStripeAccount = (req, res) => {
stripe.accounts.create({
type: 'express',
country: 'US',
email: req.user.email
})
.then(account => {
console.log('Account: ', JSON.stringify(account))
stripe.accountLinks.create({
account: account.id,
refresh_url: 'https://app.com/reauth',
return_url: 'https://app.com/return',
type: 'account_onboarding',
})
.then(accountLinks => {
console.log('Account links: ', accountLinks.url)
return res.send(accountLinks)
})
.catch(err => {
console.log("Error fetching account links from Stripe: ", err.message);
return res.status(500).send({
message: err.message || "An error has occured while fetching account links from Stripe."
});
})
}).catch(err => {
console.log("Error creating Stripe account: ", err.message);
return res.status(500).send({
message: err.message || "An error has occured while creating Stripe account."
});
});
};
Define the function first, export it later.
function getme() {
// ...
}
function createStripeAccount() {
// ...
getme(...);
// ...
}
exports.getme = getme;
exports.createStripeAccount = createStripeAccount;
use this.getme(...) wherever you want to use inside createStripeAccount function.
Related
I am trying to create a login functionality for my Reactjs Webiste using Nodejs express backend.
I want to set a JWT token when the user tries to log in and update that token in my mongoDB database and then verify the token on the frontend and save it to localStorage.
However, when the user tries to log in after registration, it returns back the result without the token, and thus not allowing the user to log in, unless he clicks the login button again, then my code would generate and update the user with the JWT token.
Why is this behavior happening? Why is the first response only returning the found user from the findOne() operation when i am resolving the result from the findOneAndUpdate operation?
Here is my code:
Auth Controller:
login(params) {
params.email = params.email.toLowerCase();
return new Promise((resolve, reject) => {
db.collection("Users").findOne({ email: params.email }).then((response) => {
console.log(response)
if(response) {
bcrypt.compare(params.password, response.password, (err, success) => {
if(success) {
let token = jwt.sign({
name: response.name,
id: response._id
}, proccess.env.JWT_SECRET);
db.collection("Users").findOneAndUpdate({
email: params.email
}, {
$set: { token: token, lastLogin: new Date() },
}, function (e, s) {
if(e) {
console.log(e)
reject(e)
} else {
console.log("updated")
resolve(s)
}
})
} else {
reject({msg: 'Incorrect email or password.'})
}
})
} else {
reject({msg: 'cannot log in user'});
}
})
})
}
Auth Router:
router.post('/login', (req, res) => {
let User = new models.User()
let processes = [];
processes.push(function (callback) {
User.login(req.body).then(function (response) {
callback(null, response);
}, function (error) {
console.log(error)
callback(error);
});
});
async.waterfall(processes, function (error, data) {
if (!error) {
return res.json({
statusCode: 200,
msg: 'User logged in successfully.',
result: data
});
} else {
return res.json({
statusCode: 401,
msg: 'Cannot login user.',
error: error
});
}
});
})
React Login.js:
const login = () => {
axios.post('/login', data).then(async (response) => {
console.log(response)
if(response && response.data.result.value.token ) {
localStorage.setItem("authUser", JSON.stringify(response.data.result.value.token))
history.push("/")
console.log(response.data.result)
} else {
console.log("ERROR")
}
})
}
MongoDBs method findOneAndUpdate does return the old document by default.
In order to return the updated document pass returnNewDocument: true as option:
https://www.mongodb.com/docs/manual/reference/method/db.collection.findOneAndUpdate/
In your case:
db.collection("Users").findOneAndUpdate({
email: params.email
}, {
$set: { token: token, lastLogin: new Date() },
}, {
returnNewDocument: true
}, function (e, s) {
if(e) {
console.log(e)
reject(e)
} else {
console.log("updated")
resolve(s)
}
})
PS: You might should use async functions with await. This could make your code way more readable (at least within the User Model) :)
This can help you.
In your model
async login(params) {
params.email = params.email.toLowerCase();
try {
const user = await db.collection("Users").findOne({ email: params.email });
if(!user) {
throw {message: "Incorrect email"}
}
const vaild = await bcrypt.compare(params.password, user.password);
if(!valid) {
throw {msg: 'Incorrect email or password.'}
}
let token = jwt.sign({
name: user.name,
id: user._id
}, proccess.env.JWT_SECRET);
return db.collection("Users").findOneAndUpdate({
email: params.email
}, {
$set: { token: token, lastLogin: new Date() },
}, {new: true}); //FOR THE RETRIEVE NEW UPDATEs FROM MONGODB
} catch(e) {
throw e
}
}
Im currently writing a RESTful API for a webservice but im having trouble. Im trying to delete an mail, but first i want to check if the mail even exists. My problem is that it doesn't check if mail is null and doesn't respond with a 404. Im working with express and mongoose
router.delete('/:id', (req, res) => {
const { id } = req.params;
Mail.findById(id)
.exec()
.then((mail) => {
if (!mail) {
console.log(mail) // returns null
return res.status(404);
}
})
.then(
Mail.deleteOne({ _id: id })
.exec()
.then(() => {
res.status(200).json({
message: 'Mail deleted',
});
})
.catch((err) => {
res.status(500).json({ error: err });
})
);
});
I think you have to do the the deletion part of the code inside the first then block as an else statement. You are not returning anything that the next then block can use.
you could do:
Mail.findById(id)
.exec()
.then((mail) => {
if (!mail) {
console.log(mail) // returns null
return res.status(404).send() //need to send response;
}
Mail.deleteOne({ _id: id })
.exec()
.then(() => {
res.status(200).json({
message: 'Mail deleted',
});
})
}).catch((err) => {
res.status(500).json({ error: err });
})
PRO TIP: if you don't know it, learn async await. Code will look much cleaner!
Then it would look like this:
router.delete('/:id', async (req, res) => {
const { id } = req.params;
try {
const mail = await Mail.findById(id);
if(!mail) {
return res.status(404).send();
}
await Mail.deleteOne({_id: id});
res.status(200).json({
message: 'Mail deleted',
});
} catch(e) {
res.status(500).json({ error: err });
}
I'm trying to build a REST API in NodeJS for an online-store. My code for the POST-request looks like this:
router.post('/', (req, res, next) => {
const order = new Order({
_id: new mongoose.Types.ObjectId(),
customer_name: req.body.order.customer_name,
total_price: req.body.order.total_price,
products: req.body.order.products,
});
order
.save()
.then(result => {
req.body.order.products.forEach(value => {
let availiableQuantity = value.available_quantity - value.ordered_quantity;
Product.findOneAndUpdate({ id: value.id }, { available_quantity: availiableQuantity
})
})
res.status(201).json({
message: "Successfully created product",
createdProduct: {
customer_name: result.customer_name,
products: result.products,
}
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
The issue that I'm having is that the code in .then block is not working when I'm trying to send this POST-request, even if I try to console.log something, it doesn't do anything, everything works except the code in .then block:
.then(result => {
console.log('test')
req.body.order.products.forEach(value => {
let availiableQuantity = value.available_quantity - value.ordered_quantity;
Product.findOneAndUpdate({ id: value.id }, { available_quantity: availiableQuantity
})
})
Am I missing something out?
You can instead use async await instead of processing the next step with the then block.
router.post('/',async (req, res) => {
try{
const order = new Order({
_id: new mongoose.Types.ObjectId(),
customer_name: req.body.order.customer_name,
total_price: req.body.order.total_price,
products: req.body.order.products,
});
var result = await order.save();
req.body.order.products.forEach(value => {
let availiableQuantity = value.available_quantity -
value.ordered_quantity;
Product.findOneAndUpdate({ id: value.id }, {
available_quantity: availiableQuantity
})
res.status(201).json({
message: "Successfully created product",
createdProduct: {
customer_name: result.customer_name,
products: result.products,
}
});
} catch(e) {
res.status(500).json({
message: "Bad request",
error: e
});
}
})
It's a gym app which when a user books themselves into a class, the class saves the userId as a user which will be attending, then also in the user model you also get the classes in which the user is attending too.
Currently hitting 500 (Internal Server Error).
These are the axios calls:
deleteClassHandler = () => {
this.deleteUserClassHandler();
const data = {
userId: this.props.userId,
classId: this.props.id
}
axios.delete('/api/classes/remove', data)
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
deleteUserClassHandler = () => {
const data = {
userId: this.props.userId,
classId: this.props.id
}
axios.delete('/api/auth/remove', data)
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
The this.props.userID and this.props.id are populated fine with the right values.
These are the routes -
Classes routes:
router.delete('/remove', ClassesController.deleteUser);
Auth routes:
router.delete('/remove', UserController.deleteClass);
This are the controllers:
Classes controller -
exports.deleteUser = (req, res) => {
console.log('cl userid ', req.body.userId);
console.log('cl classid ', req.body.classId);
GymClass.findById({
_id: req.body.classId
}, 'classMembers', (err) => {
if (err) {
console.log('class up here');
res.status(401).json({
message: "Error Occured!"
})
} else {
GymClass.findByIdAndDelete({
"classMembers.userId" : mongoose.Types.ObjectId(req.body.userId)
}, (err) => {
if(err) {
console.log('class down');
res.status(401).json({
message: "Error Occured!"
})
} else {
res.status(200).json({
message: "Success!"
})
}
});
}
})
}
Auth controller -
exports.deleteClass = (req, res) => {
console.log('auth userid', req.body.userId);
console.log('auth classid', req.body.classId);
User.findById({
_id: req.body.userId
}, 'bookedClasses', (err) => {
if (err) {
console.log('auth up here');
res.status(401).json({
message: "Error Occured!"
})
} else {
GymClass.findByIdAndDelete({
"bookedClasses.classId" : mongoose.Types.ObjectId(req.body.classId)
}, (err) => {
if(err) {
console.log('auth down here');
res.status(401).json({
message: "Error Occured!"
})
} else {
res.status(200).json({
message: "Success!"
})
}
});
}
})
}
I am by no means a backend superstar and I have hit a brick wall with this one, does anyone here know how I could maybe possibly change the code and the way I am tackling this? Any issues spotted? I have got a 500 server error and I am not sure what to do. I can always post the two models for the user and classes if needed.
This was also something I tried but did not work -
axios.delete('/api/classes/remove', {
data: {
userId: this.props.userId,
classId: this.props.id
}
})
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
Hello I would like to update a document in my db using findByIdAndUpdate only doing minimal calls, but some values have to be pushed onto an array and other updated.
i'm sure there must be an easy way to make this into one route instead of using the two
router.put('/notes/:id', (req, res) => {
Player.findByIdAndUpdate({
_id: req.params.id
}, {
$push: {
notes: req.body.notes
}
}, {
new: true
})
.then(player => res.status(200).json(player))
.catch(err => res.status(400).json({
'err': 'updating went wrong'
}))
})
router.put('/:id', (req, res) => {
let updates = {};
if (req.body.first) {
updates.first = req.body.first;
}
if (req.body.last) {
updates.last = req.body.last;
}
if (req.body.school) {
updates.school = req.body.school;
}
if (req.body.rank) {
updates.rank = req.body.rank;
}
Player.findByIdAndUpdate({
_id: req.params.id
}, updates, {
new: true
})
.then(player => res.status(200).json(player))
.catch(err => res.status(400).json({
'err': 'updating went wrong'
}))
})