ReferenceError: phone is not defined - node.js

What im trying to do is to create clients. From the front end, Im getting requests in an array of more than one client(fullName, phone).
To create them in MongoDB I iterate the req.body.
exports.createTrustees = asyncHandler(async (req, res, next) => {
req.body.forEach( async (user) => {
const {fullName, phone} = user;
users = await Users.create({
fullName,
phone,
});
})
res.status(200, `The user : ${phone} has been registerd!`).json({
success: true,
data: users,
});
});
This code it won't work, it shows this error: ReferenceError: phone is not defined
How can I solve this?

You don't say which instance of phone is not defined, but I am assuming the one in the res.status line.
You are defining the phone variable inside the req.body.forEach( async (user) code block - therefore it is only visible (or has scope) within that code block.
You will need to declare a variable phone at a higher level e.g.
let phone2;
req.body.forEach( async (user) => {
const {fullName, phone} = user;
phone2 = phone;
users = await Users.create({
fullName,
phone,
});
})
res.status(200, `The user : ${phone2} has been registerd!`).json({
success: true,
data: users,
});

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({ ... })

Update record based on username given in Request body

I need to update value in Group db Group_name to the value send in Json payload.
Db schema
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
username: String,
Group_name: {
type: String,
default: '',
}
});
mongoose.model('User', UserSchema);
And API request
router.put('/join', async(req, res) => {
try {
const data = await User.updateOne(req.params.username, {
Group_name: req.body.Group_name
});
console.log(data)
res.send({ msg: "Group Updated!!!" })
} catch (err) {
console.error(err.message);
res.sendStatus(400).send('Server Error');
}
});
currently its updating only first record which is incorrect , my requirement is to check for all records based on username given and according to username given in request parameters ,i will update value of Group_name to the value sent in request body.
can anyone help me ?
Modify query condition.
const data = await User.updateOne(
{ username: req.params.username },
{ $set: { Group_name: req.body.Group_name } }
);
First of all, understand the difference between req.body & req.params
req.body means hidden parameters sent in request body like in post or put requests.
req.params means defined paramters in URL. For this, you must have it defined in your route like below
router.put('/join/:username', async (req, res) => {
// ^^^^^^^^ here it is defined, now you can access it like
const username = req.params.username;
//or
const {username} = req.params; // destructuring
}
there is one more thing and that is
req.query means undefined paramters attached to URL with ?/&
If you want to give username without pre defining like /join?username=john then use req.query
router.put('/join', async (req, res) => {
const {username} = req.query;
}
Then you should use updateMany() function instead of updateOne()
try {
const {username} = req.params;
const {Group_name} = req.body;
const data = await User.updateMany(
{username}, // find as many users where username matches
{Group_name} // update group name from body
);
console.log(data);
The consoled data would be like { n: 2, nModified: 2, ...} because the update queries don't return updated documents but status of the query. If you want to get updated record set, you have to query again with find().
// after update
const updatedRecord = await User.find({ username });
console.log(updatedRecord);
::POSTMAN::
Postman has two types of parameters
Params
Body
If you add in Params it will be added in URL /join?username=john#email.com&Group_name=GroupB and you have to access it in code with req.query.username or req.query.Group_name
If you add in Body it will be hidden and can be accessed with req.body.Group_name etc
Hope it helps!

How to get Json Data from MongoDB against a specific User who posted it?

router.post('/',auth, async (req, res) => {
const { error } = validate(req.body); //Error Check
if (error) return res.status(400).send(error.details[0].message);
let property = new Property({ //Creating Object: Property as per defined Schema:
title: req.body.title,
description: req.body.description,
price: req.body.price,
user: {
_id: req.user._id, //Getting the ID from auth middleware with JWT Token Authenticared
}
});
console.log({property});
await property.save(); //Saving the Object
res.send(property); //Displaying User with created Object i.e. Property
});
I'm Creating a Property using POST Method.
Now I want to Get the Data from MongoDB, but only for the user who's currently logged in and created that data.
//Writing a GET METHOD to List of Properties with Valid Token:
router.get('/', async (req,res)=>{
try{
//Getting the Information of User by the current user.id loggin in: ... .select('-password') sets it to don't show password
const property = await Property.findById(req.user );
res.send(property);
}
catch (ex){
console.error(ex.message);
}
});
Instead of findByIdtry find({user: req.user._id}).
req.user contains the authenticated user's information so by using _id we can get can the ID which helps us filter the Properties created by a Specific User

Express - How to exclude a field from the response returned by Model.findOne() and Model.create() mongoose

I want to exclude the user's password field when sending a response to my front end. of course, I don't want anyone to access the user's encrypted password.
I have looked at this SO question, but the solution does not look good for models with many fields.
I'm using .select('-password') with Model.find(), Model.findById(), and Model.findByIdAndUpdate()
but It's not working for Model.findOne() and Model.create()
How can I exclude some fields when returning a response ?
/**
* #desc Authenticate User
* #route /api/acccounts/signin
* #access Public
*/
export const authenticateUser = asyncHandler(async (req, res) => {
const values = await loginSchema.validateAsync(req.body);
const { email, password, rememberMe } = values;
const account = await Account.findOne({ email });
if (account && (await account.matchPassword(password))) {
return res.json({
id: account.id,
firstName: account.firstName,
lastName: account.lastName,
email: account.email,
isAdmin: account.isAdmin,
...other fields,
token: generateToken(account.id, rememberMe),
});
}
return res.status(400).json({ message: 'Invalid email or password' });
});
Here you can use projection to exclude the field in your response like this
db.collection.findOne({
email: "sample#sample.com"
},
{
password: 0
})
Here is like of playground to test it: MongoPlayground
For more details check out findOne official documentation

React-Admin displays data from mongoDB but I cannot Edit

I'm using React Admin for the first time, and my users (coming from mongoDB) are displayed just fine. The problem occurs when I click the "edit" (or "delete") button on a specific user: it says "GET http://localhost:3002/api/users/2a1a3a61-f73b-4a01-b609-ae4bb815f59e 404 (Not Found)"
I use "http://localhost:3002/api/users" to make the GET req to mongoDB: "app.use('/api/users', require('./api/GetUsers'))" and "2a1a3a61-f73b-4a01-b609-ae4bb815f59e" is the id of the user I clicked.
I remember when I first started testing React Admin, that I was using jsonplaceholder.typicode to get data and the edit function was working as well, although, of course, would not persist on refresh.
What am I missing? Is the problem the fact that my api's (http://localhost:3002/api/users) purpose is only getting the data and not post/put also, maybe?
/api/GetUsers
const express = require('express');
const mongoose = require('mongoose');
const ContactUser = require('../DB/ContactUser');
const router = express.Router();
const getUsers = async (req, res) => {
ContactUser.find()
.exec((err, user) => {
if(err){
res.json(err);
} else {
res.setHeader('Access-Control-Expose-Headers', 'Content-Range');
res.setHeader('Content-Range', 'users 0-20/20');
res.json(user);
}
})
};
router.route('/').get(getUsers);
module.exports = router;
/DB/ContactUser
const mongoose = require('mongoose');
const contactUser = new mongoose.Schema({
name: String,
email: String,
message: String,
id: String
});
module.exports = mongoose.model('contactUser', contactUser);
You're missing a second route to retrieve not a list of users, but a single user. It will use the id in the URL to find one user. Something like:
router.get('/:id', function(req, res) {
ContactUser
.findOne({ _id: req.params.id })
.exec((err, user) => err ? res.json(err) : res.json(user));
});

Resources