'TypeError: Cannot read property '_id' of undefined when giving POST request
I have created an entire backend for creating categories for my blog application.
Tech. Used: MongoDB, express-jwt, jwt
Different Files are:
server.js
......
// middlewares
app.use(express.urlencoded({extended: false}));
app.use(express.json());
app.use(morgan('dev'));
app.use(cookieParser());
// cors
if(process.env.NODE_ENV == 'development') {
app.use(cors({origin: `${process.env.CLIENT_URL}`}));
}
// routes middleware
app.use('/api', authRoutes);
app.use('/api', userRoutes);
app.use('/api', blogRoutes);
app.use('/api', categoryRoutes);
app.use('/api', tagRoutes);
// port
const port = process.env.PORT || 8000;
// Listening App
app.listen(port, () => {
console.log(`Server is running on PORT ${port}`);
})
caregory.js (Routes)
const express = require('express');
const router = express.Router();
const { create, list, read, remove } = require('../controllers/category')
// Validators
const { runValidation } = require('../validators');
const { categoryCeateValidator } = require('../validators/category');
const { requireSignin, adminMiddleware } = require('../controllers/auth');
router.post('/category', categoryCeateValidator, runValidation, requireSignin, adminMiddleware, create);
router.get('categories', list);
router.get('category/:slug', read);
router.delete('category/:slug', requireSignin, adminMiddleware, remove);
module.exports = router;
category.js (controllers)
const Category = require('../models/category');
const slugify = require('slugify');
const { errorHandler } = require('../helpers/dbErrorHandler');
exports.create = (req, res) => {
const {name} = req.body;
let slug = slugify(name).toLowerCase()
let category = new Category({name, slug});
category.save((err, data) => {
if(err) {
return res.status(400).json({
error: errorHandler(err)
})
}
res.json(data);
})
}
exports.list = (req, res) => {
Category.find({}).exec((err, data) => {
if(err) {
return res.status(400).json({
error: errorHandler(err)
});
}
res.json(data);
});
};
exports.read = (req, res) => {
const slug = req.params.slug.toLowerCase()
Category.findOne({slug}).exec((err, category) => {
if(err) {
return res.status(400).json({
error: errorHandler(err)
});
}
res.json(category);
})
}
exports.remove = (req, res) => {
const slug = req.params.slug.toLowerCase()
Category.findOneAndRemove({slug}).exec((err, data) => {
if(err) {
return res.status(400).json({
error: errorHandler(err)
});
}
res.json({
message: 'Category Deleted Successfully'
});
})
}
signin function
exports.signin = (req, res) => {
const { email, password } = req.body;
// check if user exist
User.findOne({ email }).exec((err, user) => {
if (err || !user) {
return res.status(400).json({
error: 'User with that email does not exist. Please signup.'
});
}
// authenticate
if (!user.authenticate(password)) {
return res.status(400).json({
error: 'Email and password do not match.'
});
}
// generate a token and send to client
const token = jwt.sign({ _id: user._id }, process.env.JWT_SECRET, { expiresIn: '1d' });
res.cookie('token', token, { expiresIn: '1d' });
const { _id, username, name, email, role } = user;
return res.json({
token,
user: { _id, username, name, email, role }
});
});
};
requireSignin Middleware
exports.requireSignin = expressJwt({
secret: process.env.JWT_SECRET,
algorithms: ['HS256'],
userProperty: "auth"
});
authMiddleware
exports.authMiddleware = (req, res, next) => {
const authUserId = req.user._id;
User.findById({ _id: authUserId }).exec((err, user) => {
if (err || !user) {
return res.status(400).json({
error: 'User not found'
});
}
req.profile = user;
next();
});
};
adminMiddleware
exports.adminMiddleware = (req, res, next) => {
const adminUserId = req.user._id;
User.findById({ _id: adminUserId }).exec((err, user) => {
if (err || !user) {
return res.status(400).json({
error: 'User not found'
});
}
if (user.role !== 1) {
return res.status(400).json({
error: 'Admin resource. Access denied'
});
}
req.profile = user;
next();
});
};
Problem: When I POST a request using Postman in order to make a category which is as follows:
Headers and other data I used:
Solutions I have found online and followed:
- Initially was using body-parser.json() and changed it to express.json() (latest versions support JSON parsing)
- Tried both urlencoded extended: true and false.
- Checked thoroughly my entire code for any mistakes (couldn't find any particular).
- Checked server.js to ensure that I have defined middleware first then the routes.
Still, this issue persists and I am unable to find a solution.
I am new to backend development and I am unaware of any basic mistakes I may have committed here. I request you to help me find a solution as I am stuck here for days.
I'll be a great help if I can get this sorted out.
Thanks.
Solution 1:[1]
I am also facing a different error in requireSignin Middleware, if I am using the secret in back ticks then following error comes:
[enter image description here][1]
export const requireSignin = expressJwt
({
secret: `${process.env.JWT_SECRET}`,
algorithms: ["HS256"], // added later
requestProperty: "user",
});
And if I change my code to this:
export const requireSignin = expressJwt({
secret: process.env.JWT_SECRET,
algorithms: ["HS256"], // added later
requestProperty: "user",
});
Then following error occurs:
[enter image description here][2]
And if I hard code my jwt secret then no error comes, if anyone knows how to rectify it please explain.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Sagar Maheshwari |