How do I get the logged-in User ID when creating a post request for that user without using req.params.id? - node.js

Let's say I have an API with a /posts endpoint. Each post in my Mongoose schema has a reference to the user that created it, and each user has an array of references to the posts they created.
When posting as a logged-in user, in order to save that reference I need to send the current logged-in user ID along with the content of the post to the /posts endpoint. I would prefer not to do so through some nested query like /users/:id/posts and then send req.params.id. I would like to post directly to /posts but send the user.id in the request somehow.
User model:
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
posts: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}]
});
Posts model:
const PostSchema = new Schema({
content: {
type: String,
required: true
},
created: {
type: Date,
default: Date.now
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
Create new post (need a way to get the user ID since it won't actually be in req.params)
exports.createPost = async function(req, res, next) {
try {
const { content } = req.body; // ideally would get user ID from here
const post = await db.Post.create({
content,
user: req.params.id
});
const postUser = await db.User.findById(req.params.id);
postUser.posts.push(post.id);
await postUser.save();
const newPost = await db.Post.findById(post.id);
const {id, created} = newPost;
return res.status(201).json({
id,
content,
created
})
}
catch(err) {
return next(err);
}
}
I know I'm probably missing something obvious, but I appreciate any suggestions.

Related

How to find value inside array of object with mongoose?

I have events system with different role for each event (same user could be different role in different events).
I created collection of the users and this is the schema that i used:
const userSchema = new mongoose.Schema(
{
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
permissions: [{
eventId: { type: mongoose.Schema.Types.ObjectId, required: false, ref: 'Event' },
role: { type: String, required: false }
}]
},
{timestamps: true}
);
For check if the user is allowed to get this event I created middleware that need to check if the eventId is exist in the User collection under "permissions"
so this is the code that I was create:
const authorization = async (req, res, next) => {
try {
const eventId = req.params.id;
const token = req.headers.authorization.split(' ')[1]
const tokenDecoded = jwt.verify(token, process.env.JWT_SECRET);
const userId = tokenDecoded.id
console.log(userId)
const userPermissionCheck = await User.find({ _id: userId, 'permissions.eventId': { $in: eventId } } );
console.log(userPermissionCheck)
next();
} catch (error) {
res.status(401).json({ message: 'Auth failed.' })
}
}
My problem is that my find function in the authorization middleware is not working...
What the correct way to search key of object in array with mongoose?
thanks
It seems that you are on the right track from your code, but you do not need the $in operator. You should be able to do the following:
const userPermissionCheck = await User.find({ _id: userId, 'permissions.eventId': eventId });

MongoDB populate() to dynamically load/migrate data not working

I am building an app in which the user adds and deletes objects (Pic) in an array('pics') after registering, but not sure how to dynamically load or populate('pics') to userSchema to automatically render. The user registers on the app with that array originally empty ('pics' = zero), and will create or delete those objects thereafter when logged in.
Following the documentation, I used "await User.find().populate('pics');" to migrate data in index method, but did not work.
Besides, should I include 'pics' key at store method, or userSchema 'pics' should be enough?
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
pics: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Pic"
}
],
});
const picSchema = new mongoose.Schema({
thumbnail: String,
description: String,
dev: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
},
);
const User = mongoose.model('User', userSchema);
const Pic = mongoose.model('Pic', picSchema)
async index(req, res, next) {
const users = await User.find().populate('pics');
res.status(200).json(
devs
);
},
async store(req, res) {
try {
const { name } = req.body;
let user = await User.create({
name,
pics
})
// await user.populate('pics').execPopulate();
res.send({ user })
}
} catch (error) {
res.status(400).send(error);
}
},
I worked a time ago with MongoDB and NodeJS. I think that you have a problem with the definitions. Also, you can read the documentation https://mongoosejs.com/docs/populate.html
You need to define the _id for collections (Schema).
const userSchema = new mongoose.Schema({
_id: new mongoose.Types.ObjectId(),
name: {
type: String,
required: true,
trim: true
},
pics: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Pic"
}
],
});
const picSchema = new mongoose.Schema({
_id: new mongoose.Types.ObjectId(),
thumbnail: String,
description: String,
dev: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
},
);
So, when you create a new User, the _id is completed (you can generate it or it can be generated automatically) and ignore the field pics. When you create a Pic, you need to read the _id of the User and assigned as 'dev', something like:
let pic = new Pic({
thumbnail: '', description: '',
dev: yourUser._id
});
Using this way to create documents, you can use the populate function.

how to fetch user details from populated table in nodejs?

I have two tables in my MongoDB cluster i.e Post and User. Actually I want to retrieve the username and userID along with a post from the post table when a user posts something.
my post controller
router.getPostsList = async (req, res) => {
try {
const posts = await Post.list();
return res.status(200).json(posts);
} catch (err) {
return res.status(400).json(err);
}
};
MongoDB Post collection Image
PostSchema
const PostSchema = new mongoose.Schema(
{
text: {
type: String,
trim: true
},
slug: {
type: String,
trim: true,
lowercase: true
},
user: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
]
},
{ timestamps: true }
);

How to save a refrence between 2 collections in MongoDB?

I'm developing an app using Node.js, Mongoose, MongoDb, express.
I have 2 schemas one for student and one for snippets. I'm using the population model population model. I can create a user, and create a snippet and link it to the user. But I can't link and save the snippets in the user collection.
How to link and save the user so that it can have a reference to his snippets?
user and snippet schema
var userSchema = Schema({
name: { type: String, required: true, unique: true },
password: { type: String, required: true },
snippet: [{ type: Schema.Types.ObjectId, ref: 'Snippet' }]
})
var snippetSchema = Schema({
user: {type: Schema.Types.ObjectId, ref: 'User'},
title: String,
body: String,
createdAt: {
type: Date,
require: true,
default: Date.now
}
})
This is how I save the user which usually when the user register.
var username = request.body.name
var password = request.body.password
var newUser = new User({
name: username,
password: password
})
newUser.save().then(function () {
console.log('success')
response.redirect('/')
})
This is how I save the snippets I add it inside a user .save() function so that it saves the snippet ref but it gives me name.save() is not a function error.
var name = request.session.name.name
name.save().then(function () {
// Using a promise in this case
var newSnippet = new Snippet({
user: name._id,
title: title,
body: snippet
})
newSnippet.save().then(function () {
// Successful
console.log('success')
response.redirect('/')
})
}).catch(function (error) {
console.log(error.message)
response.redirect('/')
})
name.save() is not a function because name is just a string in this case, not a Mongoose object.
One way to do it is to create your user, then retrieve it and add a snippet:
var name = request.session.name.name
User.find({ name: name }).then(function (user) {
// Here you get your user by name
var newSnippet = new Snippet({
user: user._id, // And here you can pass user _id
title: 'your title',
body: 'your snippet'
})
newSnippet.save()
})

Mongoose find documents where field = req.body.user

I have a user schema and a post schema, wherein a user has many posts. I would like to return all posts that the user has on a route called '/post/dashboard'.
Here is my schemas:
let UserSchema = new Schema({
username: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
default: null,
},
profile_pic: {
type: String,
default: '/img/profilepic.png',
},
posts: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}
})
let PostSchema = new Schema({
title: {
type: String,
},
description: {
type: String,
}
original_poster: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
tags: {
type: [String]
}
})
So, for example something like:
app.get('/', (req,res) => {
Post.find({ original_poster: req.session.user }).then((posts) =>{
res.send(JSON.stringify(posts));
}) //where req.session.user is an id (the logged in user's object id or _id)
})
Essentially in sql syntax it might be something like:
SELECT * FROM POSTS WHERE ORIGINAL_POSTER = <req.session.user>
What is the proper way to return all posts by the req.session.user?
It seems that original_poster field represent a reference to User's model, If req.session.user is stored as a string you have to cast it to objectID:
const mongoose = require('mongoose');
...
let userId = mongoose.Types.ObjectId(req.session.user);
Post.find({ original_poster: userId }).then((posts) => {
res.send(JSON.stringify(posts));
});

Resources