i have this code i am trying to write, the code is supposed to update the balance in MongoDB after properly computing the balance. The challenge is , it does not, it properly computes the balance, but updating the column for the user, it does not update. Looking out to see where and how to update the balances only I have not seen anything to help.
My code is Looking thus :
const router = require("express").Router();
const User = require("../models/User");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
router.post("/update-balance/:email", async (req, res) => {
try {
if (
!req.headers.authorization ||
!req.headers.authorization.startsWith("Bearer ") ||
!req.headers.authorization.split(" ")[1]
) {
return res.status(422).json({ message: "Please Provide Token!" });
}
const amount = parseInt(req.body.amount);
const user = await User.find({ email: req.params.email });
const balance = parseInt(user[0].balance);
//return balance;
//console.log(balance);
const total_amt = amount + balance;
//console.log(total_amt);
// update Balance
const wallet_user = new User();
try{
await wallet_user.updateOne({email : req.params.email}, {$set: {balance: total_amt}});
}catch(err){
console.log(err);
}
return res.send({ error: false, message: "OK" });
} catch (error) {
res.status(404).json({ message: error.message });
}
});
module.exports = router;
What Am I suppose to do that i am not doing rightly, kindly help.
The code above shows What I have attempted..
You can use $inc:
router.post('/update-balance/:email', async (req, res) => {
try {
if (
!req.headers.authorization ||
!req.headers.authorization.startsWith('Bearer ') ||
!req.headers.authorization.split(' ')[1]
) {
return res.status(422).json({ message: 'Please Provide Token!' });
}
const amount = parseInt(req.body.amount);
try {
await User.findOneAndUpdate(
{ email: req.params.email },
{ $inc: { balance: amount } }
);
} catch (err) {
console.log(err);
}
return res.send({ error: false, message: 'OK' });
} catch (error) {
res.status(404).json({ message: error.message });
}
});
Related
I want to do this in Node.JS
I want to have a link like this, it should be a GET Request
http://localhost:3000/api/bal/update-balance?email=aa#email.com&amount=4500
How can I do this in Node.JS
My code is looking Thus
const router = require("express").Router();
const User = require("../models/User");
const Trans = require("../models/Transactions");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
router.post("/update-balance", async (req, res) => {
try {
if (
!req.headers.authorization ||
!req.headers.authorization.startsWith("Bearer ") ||
!req.headers.authorization.split(" ")[1]
) {
return res.status(422).json({ message: "Please Provide Token!" });
}
const amount = parseInt(req.body.amount);
const user = await User.find({ email: req.body.email });
const balance = parseInt(user[0].balance);
//return balance;
//console.log(balance);
const total_amt = amount + balance;
//console.log(total_amt);
// update Balance
//const wallet_user = new User();
try{
await User.findOneAndUpdate({email : req.body.email}, {$set: {balance: total_amt}});
const transactions = new Trans({
email: req.body.email,
narration: 'NEW DEPOSIT - '+amount,
credit: amount,
debit: 0.00,
amount: amount,
});
transactions.save();
}catch(err){
console.log(err);
}
return res.send({ error: false, message: "OK" });
} catch (error) {
res.status(404).json({ message: error.message });
}
});
module.exports = router;
Please See above Code.
router.get(("/update-balance"), async( req,res) => {
try {
const amount = req.query.amount;
const email = req.query.email;
//you can do the rest of the work here
}
catch (error) {
res.status(500).json({ message: error.message })
}
})
I want to be able to search by email (Just like it is done with MySQL) and it gives me the result expected in MongoDb
there are two things
1.) I want to have aquery where i can search for everything with MongoDB and get everything vis Email
My code is looking thus
const router = require("express").Router();
const Transaction = require("../models/Transactions");
router.get("/get-transactionby-email/:email", async (req, res) => {
try {
if (
!req.headers.authorization ||
!req.headers.authorization.startsWith("Bearer ") ||
!req.headers.authorization.split(" ")[1]
) {
return res.status(422).json({ message: "Please Provide Token!" });
}
const trans = await Transaction.findById(req.params.email);
res.status(200).json(trans);
} catch (error) {
res.status(404).json({ message: error.message });
}
});
module.exports = router;
But I am getting this Error back at Postman:
{
"message": "Cast to ObjectId failed for value \"john_kross2#yopmail.com\" (type string) at path \"_id\" for model \"Transactions\""
}
2.) How do i get all credits tranactions when I have colums called credit , debit and amount in the database using Node.js and Mongo DB
I managed to get it to work.
The code is looking thus :
const router = require("express").Router();
const Transaction = require("../models/Transactions");
router.get("/get-transactionby-email/:email", async (req, res) => {
try {
if (
!req.headers.authorization ||
!req.headers.authorization.startsWith("Bearer ") ||
!req.headers.authorization.split(" ")[1]
) {
return res.status(422).json({ message: "Please Provide Token!" });
}
const trans = await Transaction.find({email: req.params.email});
res.status(200).json(trans);
} catch (error) {
res.status(404).json({ message: error.message });
}
});
router.get("/get-credit-transaction/:email", async (req, res) => {
try {
if (
!req.headers.authorization ||
!req.headers.authorization.startsWith("Bearer ") ||
!req.headers.authorization.split(" ")[1]
) {
return res.status(422).json({ message: "Please Provide Token!" });
}
const trans = await Transaction.find({email: req.params.email},{email:true,narration:true,credit:true,amount:true});
res.status(200).json(trans);
} catch (error) {
res.status(404).json({ message: error.message });
}
});
router.get("/get-debit-transaction/:email", async (req, res) => {
try {
if (
!req.headers.authorization ||
!req.headers.authorization.startsWith("Bearer ") ||
!req.headers.authorization.split(" ")[1]
) {
return res.status(422).json({ message: "Please Provide Token!" });
}
const trans = await Transaction.find({email: req.params.email},{email:true,narration:true,debit:true,amount:true});
res.status(200).json(trans);
} catch (error) {
res.status(404).json({ message: error.message });
}
});
module.exports = router;
Thanks everyone.
I have a function to check if a user exists, and a function to create a new user in my User model.
What I want to do is call them in the router to check if a user with the email adress in req.body already exists.
If it does, I want to return a message, and if not, I want to create the user.
When I try to call the route in Postman, I get this error in node console :
node_modules/express/lib/response.js:257
var escape = app.get('json escape')
TypeError: Cannot read properties of undefined (reading 'get')
User model :
const Sequelize = require("sequelize");
const connexion = require("../database");
const User = connexion.define(
"users",
{
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
email: {
type: Sequelize.STRING(100),
allowNull: false,
},
password: {
type: Sequelize.STRING(100),
allowNull: false,
},
},
{
freezeTableName: true
}
);
function checkUser(userEmail) {
const findUser = User.findOne({ where: { userEmail } }).catch((err) => {
console.log(err);
});
if (findUser) {
return res.json({ message: "Cette adresse email est déjà enregistrée" });
} else {
return false;
}
}
function createUser(userData) {
console.log(userData);
User.create(userData)
.then((user) => {
console.log(user);
})
.catch((err) => {
console.log(err);
});
}
module.exports = { createUser, checkUser };
user controller :
const createUser = require("../models/User");
const bcrypt = require("bcrypt");
const saltRounds = 10;
addUser = async (req, res) => {
try {
const userData = req.body;
console.log(req.body);
bcrypt.hash(userData.password, saltRounds, async function (err, hash) {
userData.password = hash;
const newUser = await createUser(req.body);
res.status(201).json({ newUser });
});
} catch (err) {
console.log(err);
res.status(500).json("Server error");
}
};
module.exports = addUser;
user router :
const express = require("express");
const router = express.Router();
const addUser = require("../controllers/userController");
const { checkUser } = require("../models/User");
router.post("/", async (req, res) => {
const { email } = req.body;
const alreadyExists = await checkUser(email);
if (!alreadyExists) {
addUser(req.body);
}
});
module.exports = router;
EDIT : Finally I'm trying a more simple way. I will do the check part directly into the createUser function.
But now, it creates the user even if the email already exists ^^
async function createUser(userData) {
console.log(userData);
const findUser = await User.findOne({ where: userData.email }).catch(
(err) => {
console.log(err);
}
);
findUser
? console.log(findUser)
: User.create(userData)
.then((user) => {
console.log(user);
})
.catch((err) => {
console.log(err);
});
}
i think the problem is with this part you are trying to use res but it doesn't exist in your checkUser function
if (findUser) {
return res.json({ message: "Cette adresse email est déjà enregistrée" });
} else {
return false;
}
try this instead
if (findUser) {
return true });
} else {
return false;
}
UPDATE to fix the problem of user creation if it already exists
async function createUser(userData) {
console.log(userData);
const findUser = await User.findOne({ where: userData.email }).catch(
(err) => {
console.log(err);
}
);
if(!findUser){
findUser
? console.log(findUser)
: User.create(userData)
.then((user) => {
console.log(user);
})
.catch((err) => {
console.log(err);
});
}
}
Problem solved by doing this (thanks super sub for your help):
async function createUser(userData) {
console.log(userData);
const email = userData.email;
const findUser = await User.findOne({ where: { email } }).catch((err) => {
console.log(err);
});
if (!findUser) {
User.create(userData)
.then((user) => {
console.log(user);
})
.catch((err) => {
console.log(err);
});
}
}
when i try changing password using postman everything works but when i try to do that on the frontend i don't get any errors on the backend, the password isn't changed and i get error on network tab 'id is not valid'.
here is my backend:
routes:
router.post("/reset", reset);
router.post("/reset/:userId/:token", changepw);
controllers:
export const reset = async (req, res) => {
const { email } = req.body;
try {
if (validateEmail(email) === false)
return res.status(400).json({ error: "Please enter a valid email" });
const user = await User.findOne({ email });
if (!user) return res.status(404).json({ error: "User doesn't exist" });
let token = await Token.findOne({ userId: user._id });
if (!token) {
token = await new Token({
userId: user._id,
token: crypto.randomBytes(32).toString("hex"),
}).save();
}
const link = `http://localhost:3000/auth/reset/${user._id}/${token.token}`;
// when the port is 5000 here its works on postman but when i set 3000 it doesn't work
const result = await sendEmail(user.email, link);
res.status(200).json({ result, token });
} catch (error) {
res.status(500).json({ error: "Something went wrong" });
console.log(error);
}
};
export const changepw = async (req, res, next) => {
const { password, confirmPassword } = req.body;
const { userId: _id, token } = req.params;
try {
if (!mongoose.Types.ObjectId.isValid(_id))
return res.status(400).json({ error: "Id is not valid" });
const user = await User.findById(_id);
if (!user)
return res.status(400).json({ error: "Invalid link or expired" });
const tokens = await Token.findOne({
userId: user._id,
token,
});
if (!tokens)
return res.status(400).json({ error: "Invalid link or expired" });
if (password !== confirmPassword)
return res.status(400).json({ error: "Passwords don't match" });
const hashedPassword = await bcrypt.hash(password, 12);
const result = await User.findByIdAndUpdate(
_id,
{ password: hashedPassword },
{ new: true }
);
await tokens.delete();
res.status(200).json({ result, tokens });
} catch (error) {
res.status(500).json({ error: "Something went wrong" });
console.log(error);
next(error);
}
};
here is the frontend:
this is how i connect backend and frontend:
export const reset = (email) => API.post("/auth/reset", email);
export const changepw = (pw) => API.post("/auth/reset/:userId/:token", pw);
<Route path="/auth/reset/:userId/:token" component={ChangePassword} />
// this the component where user go to change password
redux actions:
export const reset = (email) => async (dispatch) => {
try {
const { data } = await api.reset(email);
dispatch({ type: actionTypes.RESET, data });
} catch (error) {
const err = JSON.stringify(error?.response?.data);
sessionStorage.setItem("error", err);
}
};
export const changepw = (pw) => async (dispatch) => {
try {
const { data } = await api.changepw(pw);
dispatch({ type: actionTypes.CHANGEPW, data });
} catch (error) {
const err = JSON.stringify(error?.response?.data);
sessionStorage.setItem("error", err);
}
};
reducers:
export default (state = { user: null, link: null }, action) => {
switch (action.type) {
case actionTypes.RESET:
return { ...state, link: action.payload };
case actionTypes.CHANGEPW:
return { ...state, user: [state.user, action.payload] };
default:
return state;
}
};
this is what i do when user submit new password:
const [data, setData] = useState({
password: "",
confirmPassword: "",
});
const handleSubmit = async (e) => {
e.preventDefault();
dispatch(changepw({ ...data }));
setData({
password: "",
confirmPassword: "",
});
// history.push("/auth");
};
I know this question gets asked a lot but I cannot tell where I am sending multiple headers. The data is getting stored in the database and then it crashes. I am fairly new to Node/Express and I think I might be missing something fundamental here.
I have tried reading what I could find on stackoverflow and figured out the reason I am getting this error is because it is sending multiple header requests. Tried updating the code with little tweaks but nothing has worked so far.
Thanks for the help.
Dashboard Controller -
exports.getGymOwnerMembersAdd = (req, res, next) => {
let message = req.flash('error');
if(message.length > 0) {
message = message[0];
} else {
message = null;
}
const oldInput = {
...
};
Membership
.find()
.then(memberships => {
res.render('gym-owner/members-add', {
memberships: memberships,
oldInput: oldInput,
errorMessage: message,
pageTitle: 'Add Members',
path: '/gym-owner-dashboard/members-add',
validationErrors: []
});
})
.catch(err => {
console.log(err);
});
}
exports.postGymOwnerMembersAdd = (req, res, next) => {
const membershipId = req.body.membershipLevel;
const errors = validationResult(req);
let message = req.flash('error');
if(message.length > 0) {
message = message[0];
} else {
message = null;
}
if(!errors.isEmpty()) {
Membership
.find()
.then(memberships => {
return res.status(422).render('gym-owner/members-add', {
pageTitle: 'Add Members',
path: '/gym-owner-dashboard/members-add',
errorMessage: errors.array()[0].msg,
message: message,
memberships: memberships,
oldInput: {
...
},
validationErrors: errors.array()
});
})
.catch(next);
}
bcrypt
.hash(password, 12)
.then(hashedPassword => {
const user = new User({
...
});
return user.save();
})
.then(result => {
res.redirect('/gym-owner-dashboard/members');
})
.catch(err=> {
console.log(err);
});
}
Dashboard Routes And Validation-
router.get('/gym-owner-dashboard/members-add', isAuth, isGymOwner, dashboardController.getGymOwnerMembersAdd);
router.post(
'/gym-owner-dashboard/members-add',
isAuth, isGymOwner,
[
check('name')
.isAlpha().withMessage('Names can only contain letters.')
.isLength({ min: 2 }).withMessage('Please enter a valid name')
.trim(),
check('email')
.isEmail().withMessage('Please enter a valid email.')
.custom((value, { req }) => {
return User.findOne({
email: value
}).then(userDoc => {
console.log('Made it here!');
if(userDoc) {
return Promise.reject('E-mail already exists, please pick a different one.');
};
});
})
.normalizeEmail(),
...
check(
'password',
'Please enter a password at least 5 characters.'
)
.isLength({ min: 5 })
.trim(),
check('confirmPassword')
.trim()
.custom((value, { req }) => {
if(value !== req.body.password) {
throw new Error('Passwords have to match!');
}
return true;
})
],
dashboardController.postGymOwnerMembersAdd
);
Expected Results
Create a new user while passing validation.
Actual Results
A new user is created and saved to Mongodb. The user gets redirected back to the user creation page with an error that the user is undefined. The server crashes with the error "Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client"
I understand you have a bug in "postGymOwnerMembersAdd".
if(!errors.isEmpty()) {
Membership
.find()
.then(memberships => {
return res.status(422).render('gym-owner/members-add', { // this return refers to cb but not to middleware
pageTitle: 'Add Members',
path: '/gym-owner-dashboard/members-add',
errorMessage: errors.array()[0].msg,
message: message,
memberships: memberships,
oldInput: {
...
},
validationErrors: errors.array()
});
})
.catch(next);
}
bcrypt
.hash(password, 12)
.then(hashedPassword => {
const user = new User({
...
});
return user.save();
})
.then(result => {
res.redirect('/gym-owner-dashboard/members');
})
.catch(err=> {
console.log(err);
});
Thus, both the "return res.status(422).render()" and the "res.redirect('/gym-owner-dashboard/members')" will be executed, and this trigger error (header set after they are sent).
I mean two solutions to the problem
First: use async/await
exports.postGymOwnerMembersAdd = async (req, res, next) => {
const membershipId = req.body.membershipLevel;
const errors = validationResult(req);
let message = req.flash('error');
if(message.length > 0) {
message = message[0];
} else {
message = null;
}
if(!errors.isEmpty()) {
try {
const memberships = await Membership.find();
return res.status(422).render('gym-owner/members-add', {
pageTitle: 'Add Members',
path: '/gym-owner-dashboard/members-add',
errorMessage: errors.array()[0].msg,
message: message,
memberships: memberships,
oldInput: {
...
},
validationErrors: errors.array()
};
} catch (err) {
next(err);
}
}
const hashedPassword = await bcrypt.hash(password, 12);
const user = new User({
...
});
await user.save();
return res.redirect('/gym-owner-dashboard/members');
};
Second: use else
exports.postGymOwnerMembersAdd = (req, res, next) => {
const membershipId = req.body.membershipLevel;
const errors = validationResult(req);
let message = req.flash('error');
if(message.length > 0) {
message = message[0];
} else {
message = null;
}
if(!errors.isEmpty()) {
Membership
.find()
.then(memberships => {
return res.status(422).render('gym-owner/members-add', {
pageTitle: 'Add Members',
path: '/gym-owner-dashboard/members-add',
errorMessage: errors.array()[0].msg,
message: message,
memberships: memberships,
oldInput: {
...
},
validationErrors: errors.array()
});
})
.catch(next);
} else {
bcrypt
.hash(password, 12)
.then(hashedPassword => {
const user = new User({
...
});
return user.save();
})
.then(result => {
res.redirect('/gym-owner-dashboard/members');
})
.catch(err=> {
console.log(err);
});
}
}