cannot read properties of undefined "_id" - node.js

So i'm new to node.js and i've been working on a mini project, a student portal and i am stuck showing relevant courses only based on the students department and level.
student.js
var express = require('express');
var router = express.Router();
const {ensureAuthenticated} = require('../config/auth.js');
const {Student}= require('../models/schema.js');
var axios = require('axios');
var controller = require('../controller.js');
router.get('/register-courses',ensureAuthenticated,function(req, res, next) {
axios.get('http://localhost:3000/student/available-courses')
.then(
(response)=>{
console.log(response.data)
res.render('register-courses',{courses:response.data});
})
.catch(err=>{
console.log(err);
})
});
router.get('/available-courses', controller.getCourse);
module.exports = router;
ive narrowed down the problem to the req.user conditions which if i remove it renders all courses
controller.js
var {Course} = require ('./models/schema.js');
var {Student} = require ('./models/schema.js');
exports.getCourse = (req,res) =>{
const user = Student.findById(req.user._id); //problem is i cant access currently logged in user
console.log(user);
Course.find({departmentsOffering:user.department, level:user.level})
.then(items=>{
res.send(items)
})
.catch(
err=>{
console.log(err);
}
)
}

I think it's because you forgot to add the ensureAuthenticated middleware in your route declaration.
The declaration should be
router.get('/available-courses', ensureAuthenticated, controller.getCourse);

Related

I have a Route working fine with a GET and doing ERROR 404 for UPDATE and DELETE. What can I do?

Follow the code below, everything is working fine with other collections that I am using exactly the same code and handlerFactory as well with the GET call for this one but when I try to delete and update it is getting a 404 error, it is not a typo because GET is working well and the same in the handlerFactory.js as all CRUD operations are working fine with this same code and other collection:
app.js
var userRouter = require('./routes/userRoutes');
// Routes Definitions
app.use('/', viewRouter);
app.use('/api/v1/aircraft', aircraftRouter);
app.use('/api/v1/users', userRouter);
UserRoutes.js
const express = require('express');
const userController = require('../controllers/userController');
const router = express.Router();
router.get('/', userController.getAllUsers);
router
.get('/:id', userController.getUser)
.delete(userController.deleteUser)
.patch(userController.UpdateUser);
module.exports = router;
UserController.js
const user = require('../models/userModel');
const factory = require('./handlerFactory');
exports.getAllUsers = factory.getAll(user);
exports.getUser = factory.getOne(user);
exports.deleteUser = factory.deleteOne(user)
exports.UpdateUser = factory.updateOne(user);
handlerfactory.js
const catchAsync = require('../utils/catchAsync');
const AppError = require('../utils/appError');
const APIFeatures = require('../utils/apiFeatures');
exports.deleteOne = (Model) =>
catchAsync(async (req, res, next) => {
const doc = await Model.findByIdAndDelete(req.params.id);
if (!doc) {
return next(new AppError('No document found with that ID', 401));
console.log('No document found with that ID');
}
res.status(204).json({
status: 'success',
data: null,
});
});
exports.updateOne = (Model) =>
catchAsync(async (req, res, next) => {
const doc = await Model.findByIdAndUpdate(req.params.id, req.body, {
new: true,
runValidators: true,
});
if (!doc) {
return next(new AppError('No document found with that ID', 404));
}
res.status(200).json({
status: 'success',
data: {
data: doc,
},
});
});
I will answers my own question here because Daniel just come to my attention a silly mistake that I was making but I think it can still be useful to others.
If you just wanna one route per line use:
router.update('/:id', userController.updateOne);
If you are trying to use multiple routes in the same line do not forget to use .route like in the code below:
router.route('/:id').get(userController.getUser)
.delete(userController.deleteUser)
.patch(userController.UpdateUser);
Thank you very much, it may be silly but silly things happen with code every day.
Thank you all!

Node Module.export and GET to display search results from form

I'm really struggling with routing in express, specifically returning a module.export to a res.render function but I have tried every which combination of GET, POST, :q, results/, req.params, req.body and req,query and just cant seem to figure out what I'm doing wrong. I am trying to build a simple search box which renders the results. When I submit the form I can see the url req being posted in the dev tools ie, q=lonsubmit= and get come json data back but the results page never resolves. docs is never passed to the res.render. and is only available in the controller. How can I use it in the res.render('results')?
Is this because it is waiting for the results from the api? i can see the returned json if I console log. Why is the result page just hanging please?
app.js
const indexRouter = require('./routes/index');
const resultsRouter = require('./routes/results');
const postRouter = require('./routes/post');
app.use('/', indexRouter);
app.use('/', resultsRouter);
app.use('/', postRouter);
index.js
extends layout
block content
h1= title
div.container-fluid
div.row.justify-content-center
p Find Your Dream Kruger Safari Package!
form.form-inline.my-2.my-lg-0#searchBox(
action='/results'
method='GET'
)
input.form-control.mr-sm-2(type='text', placeholder='City Code ie. LON, JHB, CPT', aria-label='Search', id='q' name='q' required autofocus)
button.btn.btn-success.my-2.my-sm-0(type='submit' id='submit' name="submit") Search
routes/index.js
const express = require('express');
const router = express.Router();
router.get('/', function(req, res, next) {
res.render('index', {title: 'Safari Packages and Accommodation Bookings South Africa!'});
});
module.exports = router;
results.pug
extends layout
block content
h1= title
p Results
div.find test #{body}
div.container
div.row
div.col-sm #{doc}
p left col content
div.col-sm
tbody
each doc in list
tr
td= doc.hotel.name
routes/results.js
const express = require('express');
const router = express.Router();
router.get('/results', (req, res) => {
const q = req.query.q;
const searchAmadeus = require('../controllers/amadeusControl.js');
searchAmadeus.findNew(q, ( docs) => {
res.render('results', {
title: 'We Found Some Great Deals',
list: docs,
});
console.log('Error finding record :');
});
});
module.exports = router;
amadeusControl.js
module.exports = {
findNew: function(q, docs) {
const Amadeus = require('amadeus');
const amadeus = new Amadeus({
'clientId': process.env.AMADEUS_CLIENT_ID,
'clientSecret': process.env.AMADEUS_CLIENT_SECRET,
});
console.log('q before amadeus', q);
amadeus.shopping.hotelOffers.get({
cityCode: q,
}).then(function(response) {
console.log('q inside function', q);
const count = Object.keys(response).length;
console.log(count);
}).catch(function(error) {
console.log(error.response);
console.log(error.response.request);
console.log(error.code);
});
}};
routes/post.js
const express = require('express');
const router = express.Router();
router.post('/results', function(req, res) {
const q = req.body.q;
res.send(q);
console.log('body', q);
// res.send(q);
// console.log(q);
});
module.exports = router;

Only able to access one route from routes hierarchy

I'm attempting to access a route directly from a request, even though another subfolder works the other does not. Repeatedly throwing 404 errors. /api/getPostList works but /post/ or /post/:title doesn't work.
I've restructured the code, attempted to change it from a get request to a post request, added /post/:title to access an individual post or without a / to access the main list.
Server.js contains
app.use('/', Routes);
routes/index.js contains
const router = require('express').Router();
const posts = require('./posts');
const api = require('./api');
router.use('/post', posts);
router.use('/api', api);
module.exports = router;
routes/api/index.js contains
Api.get('/getPostList', (req, res) => {
PostModel.find(function (err, post) {
if (err) return console.log('error: ' + err);
return res.json({ postList: post});
});
console.log("Attempted to get post list on /getPost/ route: " + ++postRouteCnt);
});
Api.get('/getPost/:title', getPost);
module.exports = Api;
routes/post/index.js contains
const Posts = require('express').Router();
const post = require('./post');
const PostModel = require('../../../server/models.js');
let postRouteCnt = 0;
Posts.get('/', (req, res) => {
PostModel.find(function (err, post) {
if (err) return console.log('error: ' + err);
return res.json({ postList: post});
});
console.log("Attempted to get post list on /post/ route: " + ++postRouteCnt);
});
Posts.get('/:title', post);
module.exports = Posts;
When calling /post/ I get a 404 Cannot GET /post/ when I should receive the json response.
EDIT:
Folder structure
Server/
routes/
api/
index.js
getPost.js (for individual post)
posts/
index.js
post.js (for individual post)
server.js
Base on your structure folder, I try to write code with simple code
App.js :
const express = require('express')
const app = express()
const port = 3000
const Routes = require('./routes/posts/index.js');
app.use('/', Routes);
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
.routes/ posts/ index.js :
const express = require('express');
const router = express.Router();
const postController = require('./post');
// GET /
router.get('/posts', postController.getPosts);
module.exports = router;
.routes/ posts/ post.js :
exports.getPosts = (req,res) => {
res.send('test');
}
Try input http://localhost:3000/posts and its work
You can write any logic in .routes/ posts/ post.js :
try changing it like this
Posts.get('/', (req, res) => {
PostModel.find(function (err, post) {
if (err) throw err;
res.send({ postList: post});
});
console.log("Attempted to get post list on /post/ route: " + ++postRouteCnt);
});
now try this url
/post/

Why data is not getting from MongoDB when I import passport in NodeJS

I'm a beginner for NodeJS. For login functionality implement I needed to Set Up Passport to Handle the Express Authentication.
Here is my index.js
const express = require ('express');
const bodyParser = require ('body-parser');
const cors = require ('cors');
const path = require ('path');
//const passport = require ('passport');
const {mongoose} = require ('./db.js');
var employeeController = require('./controllers/employeeController.js');
var reservationController = require('./controllers/reservationController.js');
var app = express();
app.use(bodyParser.json());
app.use(cors({origin: 'http://localhost:4200'}));
app.listen(3000, () => console.log('server started at port :3000'));
app.use('/employees',employeeController);
app.use('/reservations',reservationController);
Here I commented out passport
This is my employee controller which retrieve data
const express = require ('express');
var router= express.Router();
var ObjectId = require('mongoose').Types.ObjectId;
var {Employee} = require('../models/employee');
// =>localhost:3000/employees
router.get('/',(req,res) => {
Employee.find((err,docs) => {
if(!err) {res.send(docs);}
else {console.log('error in retrieving employees :' + JSON.stringify(err,undefined,2)); }
});
});
router.get('/:id',(req,res)=>{
if(!ObjectId.isValid(req.params.id))
return res.status(400).send('No record with given id : ${req.params.id}');
Employee.findById(req.params.id,(err,doc) =>{
if(!err){res.send(doc);}
else{console.log('error in retriving employee:'+JSON.stringify(err,undefined,2));}
});
});
router.post('/',(req,res) =>{
console.log(req.body);
var emp = new Employee ({
name: req.body.name,
position: req.body.position,
office: req.body.office,
salary: req.body.salary,
});
emp.save((err,doc) => {
if(!err) {res.send(doc);}
else{console.log('error in saving employee'+ JSON.stringify(err,undefined,2));}
});
});
router.put('/:id', (req, res)=>{
if(!ObjectId.isValid(req.params.id))
return res.status(400).send('No record with given id : ${req.params.id}');
var emp = {
name: req.body.name,
position: req.body.position,
office: req.body.office,
salary: req.body.salary,
};
Employee.findByIdAndUpdate(req.params.id,{$set:emp},{new:true},(err,doc) =>{
if(!err){res.send(doc);}
else{console.log('error in updating employee:'+JSON.stringify(err,undefined,2));}
});
});
router.delete('/:id',(req,res)=>{
if(!ObjectId.isValid(req.params.id))
return res.status(400).send('No record with given id : ${req.params.id}');
Employee.findByIdAndRemove(req.params.id,(err,doc) =>{
if(!err){res.send(doc);}
else{console.log('error in deleting employee:'+JSON.stringify(err,undefined,2));}
});
});
module.exports = router;
My app is retrieving data from the mongodb perfectly. But when I remove the comment out of the passport in the index.js data retrieval not happen. I can't figure out what's went wrong when I add passport.
Please help me as I'm new one for NodeJS.
passport is not a middleware.
const path = require ('path');
const passport = require ('passport');
....
app.use(passport.initialize())
.... //your routes
Hope this solves your issue

getting 404 from a route with a param - express 4

Im trying to use a param in a route... tried the 4.x docs on express website but no use.. im still getting 404... seems like its not hitting my function..
The other routes to create and list all itens are fine..
var db = require('../db');
var express = require('express');
var mongoose = require( 'mongoose' );
var Users = mongoose.model( 'Users' );
var app = express.Router();
//PARAM
app.param('name', function(req, res, next, name) {
Users.find({name:name}, function(err, docs) {
if (err) {
return next(err);
}
else if (!name) {
return next(new Error('failed to load user'));
}
req.user = docs[0];
next();
});
});
//SHOW
app.get('/users/:name', function(req,res){
res.render('users/profile', {user: req.user});
});
tried a simple version... same 404... (btw the name exist.. it shows on the list item)
//SHOW
app.get('/users/:name', function(req, res, name){
var name = req.param('name');
Users.find({name: name}, function(err, docs) {
req.user = docs[0];
next();
});
res.render('users/profile', {user: req.user});
});
It's because you're using an Express 4 Router like it's an Express 3 app. A Router lets you set up a collection of related routes, like you have done. However, you then must attach the Router to your larger Express server.
var express = require('express');
var app = express();
var router = express.Router();
// attach some things to router
// router.get('/users/:name', ...)
app.use('/foo', router);
Would mount all the paths that router handles under the /foo path, like /foo/users/:name.

Resources