How to save req.body object with a user ID - node.js

I am trying to save the request.body object containing an authenticated user ID into a new collection called useritems.
below is the req.body object with the user ID
{contact: "90000023", item: "Bread", price: "50", id: "5f4acf21287c6226ec0855af"}
next i find user with the id "5f4acf21287c6226ec0855af"
User.findOne({_id: _id}, function(err, items){
console.log(req.body)
if (err) {
console.log('err', err);
res.status(500).send(err);
} else {
const newItem = new Item ({
name:items.name,
email:items.email,
contact:req.body.contact,
item:req.body.item,
price:req.body.price,
});
newItem.save(function (err, item) {
if (err) {
console.log(err);
} else {
res.send(item);
}
});
)
}
})
})
here is the output:
{
_id: 5f4e32006ce4d91a1cd811e2,// mongodb assigns new id. However, i still want the userID (5f4acf21287c6226ec0855af) persisted
name: 'Bernad James',
email: 'Ben#gmail.com',
contact: 90000023,
item: 'Bread',
price: 50
}
how do I make it such that I am able to maintain the userID after save in the item collection
//here is my Item schema
const ItemSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
contact: {
type: Number,
required: true
},
item: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
And my user schema
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
I want the userID persisted throughout so that i can always reference it to deal with particular authenticated logged in user

Related

MongoDB finding first user instead of the specified Email user

Im trying to find a user by their email in my MongoDB call through express and mongoose. Im getting it through a request body but at the moment it's only returning the first user in the collection or all the users in the collection, how do I find ONE user by their email address? I would obviously also like to then check their passwords...
User Schema looks like this
const users = mongoose.Schema({
Role: {
type: String,
default: 'Customer'
},
name: {
type: String,
required: true
},
password: {
type: String,
required: true
},
birthday:{
type: String,
required: true
},
displayName: String,
createdAt: {
type: Date,
default: Date.now
},
contact:{
email:{
type: String,
required: true
},
cellphone: String,
},
shippingAd:{
house:{
type: Number,
required: true,
},
road:{
type: String,
required: true,
},
complex: String,
city: {
type: String,
required: true,
},
province:{
type: String,
required: true,
},
postalCode:{
type: String,
required: true,
},
Country:{
type: String,
required: true,
},
},
newsletter:{
type: Boolean,
default: false
},
wishlist: [
{ type: mongoose.Schema.Types.ObjectId, ref: 'products'}
]
});
users.pre('save', async function(next){
try {
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(this.password, salt);
this.password = hashedPassword;
next();
} catch (error) {
next(error);
}
})
Express setup for the call
userRouter.post('/api/loginuser',async (req, res) =>{
const findUser = await userSchema.findOne({
email: req.body.email
});
if(findUser){
return res.json(findUser)
} else{
res.json(false)
}
});
Rest API call
const loginUser = (e) =>{
let payload = {
email: formValues.email,
password: formValues.password
}
axios.post('http://localhost:5001/api/loginuser', payload)
.then(res =>{
if(!res.data){
alert('There was no response from the database.')
} else{
if(res.data){
sessionStorage.setItem('user', res.data.user)
// navigate('/')
console.log(res.data)
}else{
alert('Something is wrong in the backend')
}
}
})
.catch(err =>{
console.log(err);
})
}
Your email field is nested within your contact info so in order to make a query to find a user by the email you have to search for that nest value like this.
const findUser = await userSchema.findOne({
"contact.email": req.body.email
});

How to update a specific nested array inside a MongoDB document

So I have a primary mongoDB object that has multiple documents nested within. I want to access a specific document in an array and modify one of its values. This is my document setup
const sectionSchema = new mongoose.Schema({
name: String,
items: [itemSchema],
currentAmount: {
type: mongoose.Decimal128,
default: 0
},
limitAmount: {
type: mongoose.Decimal128,
required: true
},
isActive: {
type: Boolean,
default: 0
}
});
const Section = new mongoose.model("Section", sectionSchema);
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique:true
},
email: {
type: String,
lowercase: true,
trim:true,
required: true,
unique: true
},
password: {
type: String,
required: true
},
sections: [sectionSchema]
});
const User = new mongoose.model("User", userSchema);
I've added some dummy values to fill the database, including the other testSection and testItems.
const testSection2 = new Section({
name: "Vacation",
items: [testItem3,testItem4],
currentAmount: 0,
limitAmount: 800,
isActive: 1
});
const testUser = new User({
username: "wavey123",
email: "wvy#123.com",
password: "wvy123",
sections: [testSection1,testSection2]
});
I've tried different iterations of the .findOneAndUpdate methods with no success like:
app.post("/sSelect", function(req,res){
const selectedSection = req.body.sectionName;
User.findOneAndUpdate({sections: {$elemMatch: {isActive: 1}}},{sections: {isActive: 0}},{new: true}, function(err, aSection){
if (err){
console.log(err)
}
console.log(aSection);
})
User.findOneAndUpdate(({sections: {$elemMatch: {name: selectedSection}}}),{$set: {sections: {isActive: 1}}},{new: true}, function(err, aSection){
if (aSection){
res.redirect("/");
}
})
I end up with my base document looking like this:
[
{
_id: ObjectId("629a971bb8a72843a07df0fd"),
username: 'wavey123',
email: 'wvy#123.com',
password: 'wvy123',
sections: [
{
currentAmount: Decimal128("0"),
isActive: false,
_id: ObjectId("629a9756792a3b21872c329f"),
items: []
}
],
__v: 0
}
]
This happens after the first .findOneAndUpdate. Cant seem to get my head around it.
so i just scrapped the whole .findOneAndUpdate and just used JS to find the isActive key and manipulate it like so:
app.post("/sSelect", function(req,res){
const selectedSection = req.body.sectionName;
User.findOne({}, function(err, aSection){
aSection.sections.forEach(function(section){
if(section.isActive === true){
section.isActive = false;
console.log(section.isActive)
aSection.save();
}
})
});
User.findOne({}, function(err, aSection){
aSection.sections.forEach(function(section){
if(section.name === selectedSection){
section.isActive = true;
console.log(section.name,section.isActive)
aSection.save();
}
})
});
res.redirect("/");
:)

Mongoose - Get and Delete a subrecord

I have a model defined as so:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const feedbackSchema = new Schema({
Name: {
type: String,
required: true,
},
Email: {
type: String,
required: true,
},
Project: {
type: String,
required: true,
},
Wonder: {
type: String,
required: true,
},
Share: {
type: String,
required: true,
},
Delight: {
type: String,
required: true,
},
Suggestions: {
type: String,
required: true,
},
Rating: {
type: String,
required: true,
},
dateCreated: {
type: Date,
default: Date.now(),
},
user: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
const UserSchema = new Schema({
googleId: {
type: String
},
displayName: {
type: String
},
firstName: {
type: String
},
lastName: {
type: String
},
image: {
type: String
},
createdAt: {
type: Date,
default: Date.now(),
},
feedback: [feedbackSchema],
})
module.exports = mongoose.model("User", UserSchema);
An example document:
{
_id: ObjectId('60b9dc728a516a4669b40dbc'),
createdAt: ISODate('2021-06-04T07:42:01.992Z'),
googleId: '2342987239823908423492837',
displayName: 'User Name',
firstName: 'User',
lastName: 'Name',
image: 'https://lh3.googleusercontent.com/a-/89wf323wefiuhh3f9hwerfiu23f29h34f',
feedback: [
{
dateCreated: ISODate('2021-06-04T07:42:01.988Z'),
_id: ObjectId('60b9dc858a516a4669b40dbd'),
Name: 'Joe Bloggs',
Email: 'joe#bloggs.com',
Project: 'Some Project',
Suggestions: 'Here are some suggestions',
Rating: '10'
},
{
dateCreated: ISODate('2021-06-04T08:06:44.625Z'),
_id: ObjectId('60b9df29641ab05db7aa2264'),
Name: 'Mr Bungle',
Email: 'mr#bungle',
Project: 'The Bungle Project',
Suggestions: 'Wharghable',
Rating: '8'
},
{
dateCreated: ISODate('2021-06-04T08:08:30.958Z'),
_id: ObjectId('60b9df917e85eb6066049eed'),
Name: 'Mike Patton',
Email: 'mike#patton.com',
Project: 'No More Faith',
Suggestions: 'Find the faith',
Rating: '10'
},
],
__v: 0
}
I have two routes defined, the first one is called when the user clicked a button on a feedback item on the UI which takes the user to a "are you sure you want to delete this record"-type page displaying some of the information from the selected feedback record.
A second route which, when the user clicks 'confirm' the subrecord is deleted from the document.
The problem I'm having is I can't seem to pull the feedback from the user in order to select the document by id, here's what I have so far for the confirmation route:
router.get('/delete', ensureAuth, async (req, res) => {
try {
var url = require('url');
var url_parts = url.parse(req.url, true);
var feedbackId = url_parts.query.id;
const allFeedback = await User.feedback;
const feedbackToDelete = await allFeedback.find({ _id: feedbackId });
console.log(feedbackToDelete);
res.render('delete', {
imgSrc: user.image,
displayName: user.firstName,
feedbackToDelete
});
} catch (error) {
console.log(error);
}
})
Help much appreciated
Update
You should be able to do just this:
const feedbackToDelete = await User.feedback.find({ _id: feedbackId });
Or if feedbackId is just a string, which is appears to be, you may have to do something like:
// Create an actual _id object
// That is why in your sample doc you see ObjectId('foobarbaz')
const feedbackId = new mongoose.Types.ObjectId(url_parts.query.id);
const feedbackToDelete = await User.feedback.find({ _id: feedbackId });
Original
Shouldn't this:
const allFeedback = await User.feedback; (a field)
be this:
const allFeedback = await User.feedback(); (a method/function)
?

Referencing Object Id not working in Mongoose 4.11.6

I have this problem. Basically, I have 2 schemas - a User schema and a Document schema. The Document schema has an owner which references the _id field of documents in the User collection.
The problem is that I am still able to save documents in the Document collection with owner ids that do not exist in the User collection which should not be so.
Here is my User schema and Document schema respectively
const UserSchema = new Schema({
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
email: {
type: String,
validate: [{ validator: value => isEmail(value), msg: 'Invalid email.'
}],
unique: true,
required: true,
},
password: {
type: String,
required: true,
},
isAdmin: {
type: Boolean,
default: false,
},
}, {
timestamps: true,
});
const User = mongoose.model('User', UserSchema);
And the Document Schema
const DocumentSchema = new Schema({
title: {
type: String,
required: true,
},
text: {
type: String,
},
access: {
type: String,
enum: ['public', 'private'],
default: 'public',
},
owner: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
}, {
timestamps: true,
});
const Document = mongoose.model('Document', DocumentSchema);
Any help will be appreciated thanks.
For that situation you can add pre save function in your Document schema that will call before save your Document.
const DocumentSchema = new Schema({
// ...
}, {
timestamps: true,
});
DocumentSchema .pre("save",function(next) {
var self = this;
if (self.owner) {
mongoose.models['User'].findOne({_id : self.owner }, function(err, existUser){
if(err){
return next(false, err);
}
if(!existUser)
return next(false, "Invalid user reference");
else
return next(true);
});
} else {
next(false, "Owner is required");
}
});
const Document = mongoose.model('Document', DocumentSchema);

Mongoose Discriminators unable to add dicriminator details

Im currently working on adding discriminators to my express rest api. I have added different types of users to the user schema using the discriminators as different user require additional information. The problem I am facing is that when I post to the api get no errors when adding the information and only the general information is added to the schema, the details within the discriminators are ignored.
The schema is as follows:
var options = { discriminatorKey: 'type' };
var UserSchema = new Schema({
local: {
email: {
type: String,
sparse: true,
lowercase: true,
},
password: { type: String },
},
facebook: {
id: String,
token: String,
email: String,
name: String,
profileIMG: String,
},
twitter: {
id: String,
token: String,
displayName: String,
username: String
},
google: {
id: String,
token: String,
email: String,
name: String,
profileIMG: String,
}
}, options);
var addressSubschema = {
street: {
type: String,
required: true
},
number: {
type: String,
required: true
},
city: {
type: String,
required: true
},
};
var workingHoursSchema = {
start: {
type: String,
required: true
},
finish: {
type: String,
required: true
}
};
var adminSchema = new Schema({
description: {
type: String,
required: true
},
category: {
type: String,
required: true
},
workingHours: workingHoursSchema,
address: addressSubschema,
workingRadius: {
type: Number,
required: true
},
}, options);
var User = mongoose.model('User', UserSchema);
var Admin = User.discriminator('AdminUser', adminSchema);
module.exports = User;
I then export the model and when saving a new user I get a success however the admin details are not saved.
User.findOne({'local.email': email}, function(err, existingUser) {
if (err) { return next(err) }
if (existingUser) {return res.status(422).json({error: "Email already exists"})}
var user = new User({
"local.email": req.body.email,
"local.password": req.body.password,
"description": req.body.description,
"category": req.body.category,
"workingRadius": req.body.workingRadius,
"street": req.body.street,
"number": req.body.number,
"city": req.body.city,
"start": req.body.start,
"finish": req.body.finish
});
user.save(function(err) {
if (err) { return next(err) }
res.json({success: true});
});
});
Im new to using the discriminator so any help is greatly appreciated.

Resources