Heroku hosted JS and EJS app crashing when users are logging in - javascript

I am new to programming so I don't know why this happens. Users are reporting app crashes when logging in. The app is hosted on the Heroku platform with MongoDB. Can anyone tell me what the problem might be? P.S. I don't know if there is any other way to show the code, so I'll just paste it below. The user and password for the MongoDB connection string are changed for obvious reasons.
//jshint esversion:6
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const MongoClient = require("mongodb").MongoClient;
const app = express();
const uri =
"mongodb+srv://user:password#cluster0.4wwjt.mongodb.net/anketa?retryWrites=true&w=majority";
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
app.set("view engine", "ejs");
app.use(
bodyParser.urlencoded({
extended: true,
})
);
app.use(express.static("public"));
app.get("/", (req, res) => {
res.render("login");
});
app.get("/link", (req, res) => {
res.render("link");
});
app.get("/confirm", (req, res) => {
res.render("confirm");
});
app.get("/noMoreLinks", (req, res) => {
res.render("noMoreLinks");
});
app.post("/link", (req, res) => {
const username = req.body.username;
const password = req.body.password;
client.connect((err) => {
const users = client.db("anketa").collection("users");
const links = client.db("anketa").collection("links");
users.findOne({ user: username }, (err, foundUser) => {
if (err) {
console.log(err);
} else {
if (foundUser && foundUser.pass === password) {
const unvisitedLinksLength = foundUser.unvisitedLinks.length;
const currentTime = Date.now();
if (
foundUser.timeFinished &&
currentTime - foundUser.timeFinished < 18 * 60 * 60 * 1000
) {
res.render("comeTomorrow", {
headline: "Probajte opet za nekoliko sati",
});
return;
}
if (unvisitedLinksLength === 20) {
links.findOne({ id: 1 }, (err, foundLink) => {
if (err) {
console.log(err);
} else {
res.render("link", {
link: foundLink.path,
});
users.update(
{ user: foundUser.user },
{ $set: { currentLink: foundLink.id } }
);
}
});
return;
}
if (unvisitedLinksLength < 20 && unvisitedLinksLength > 0) {
let randomNumber = Math.floor(Math.random() * unvisitedLinksLength);
links.findOne(
{ id: foundUser.unvisitedLinks[randomNumber] },
(err, foundLink) => {
res.render("link", {
link: foundLink.path,
});
users.update(
{ user: foundUser.user },
{ $set: { currentLink: foundLink.id } }
);
}
);
return;
}
if (unvisitedLinksLength === 0 && foundUser.currentLink < 21) {
links.findOne({ id: foundUser.currentLink }, (err, foundLink) => {
res.render("link", {
link: foundLink.path,
});
});
return;
}
if (foundUser.currentLink === 0 && unvisitedLinksLength === 0) {
res.render("noMoreLinks");
return;
}
}
}
});
});
});
app.post("/confirm", (req, res) => {
const username = req.body.username;
client.connect((err) => {
const users = client.db("anketa").collection("users");
users.findOne({ user: username }, (err, foundUser) => {
const currentLinkId = foundUser.currentLink;
const unvisitedLinks = foundUser.unvisitedLinks;
const newUnvisitedLinks = unvisitedLinks.filter(
(linkId) => linkId !== currentLinkId
);
users.update(
{ user: foundUser.user },
{
$set: { unvisitedLinks: newUnvisitedLinks, timeFinished: Date.now() },
}
);
if (unvisitedLinks.length === 0) {
users.update({ user: foundUser.user }, { $set: { currentLink: 0 } });
return;
}
});
});
res.render("login");
});
let port = process.env.PORT;
if (port == null || port == "") {
port = 3000;
}
app.listen(port, () => {
console.log("server started successfully");
});

Related

Route.post() requires a callback function but got a [object Undefined]? Why am I getting this error?

I'm working on the backend of my react project and I seem to be having some trouble with the backend for the info. When I do npm start I get an error saying Route.post() requires a callback function but got a [object Undefined] and I'm confused as to why.
Here is my server.js file
const express = require("express");
const cors = require("cors");
const dbConfig = require("./app/config/db.config");
const app = express();
var corsOptions = {
origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));
const db = require("./app/models");
const Role = db.role;
db.mongoose
.connect(`mongodb+srv://tami00:MEUxClWqUNbLz359#cluster0.gmvao.mongodb.net/test?retryWrites=true&w=majority`, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log("Successfully connect to MongoDB.");
initial();
})
.catch(err => {
console.error("Connection error", err);
process.exit();
});
// simple route
app.use('/favourite', require('.app/routes/favourite.routes'));
// routes
// require(".app/routes/favourite.routes")(app);
require("./app/routes/auth.routes")(app);
require("./app/routes/user.routes")(app);
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
function initial() {
Role.estimatedDocumentCount((err, count) => {
if (!err && count === 0) {
new Role({
name: "user"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'user' to roles collection");
});
new Role({
name: "creator"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'creator' to roles collection");
});
new Role({
name: "watcher"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'watcher' to roles collection");
});
}
});
}
and here is my favourite.routes.js file. I have no issue with the other 2 routes.
const express = require('express');
const router = express.Router();
const{Favourite} = require("../models/favourite.model");
const {auth} = require("../middlewares/authJwt");
router.post("/favouriteNumber", auth, (req, res) => {
Favourite.find({"movieId": req.body.movieId})
.exec((err, favourite) => {
if(err) return res.status(400).send(err)
res.status(200).json({success: true, favouriteNumber: favourite.length})
})
})
router.post("/favourited", auth, (req, res) => {
Favourite.find({"movieId": req.body.movieId, "userFrom": req.body.userFrom})
.exec((err, favourite) => {
if(err) return res.status(400).send(err)
let result = false;
if(favourite.length !== 0) {
result = true
}
res.status(200).json({success: true, favourited: result});
})
})
router.post("/addToFavourite", auth, (req, res) => {
const favourite = new Favourite(req.body)
favourite.save((err, doc) => {
if(err) return res.json({success: false, err})
return res.status(200).json({success: true, doc})
})
})
router.post("/removeFavorite", auth, (req, res) => {
Favourite.findOneAndDelete({movieId: req.body.movieId, userFrom: req.body.userFrom})
.exec((err, doc) => {
if(err) return res.json({success: false, err})
return res.status(200).json({success: true, doc})
})
})
module.exports = router;
This is the favourite models where I'm creating the mongoose schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const favSchema = mongoose.Schema({
userFrom: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
movieId : {
type: String
},
movieTitle : {
type: String
},
movieImg : {
type: String
}
})
const Favourite = mongoose.model('Favourite', favSchema);
module.exports = {Favourite}
Heres the middlewares auth file
const jwt = require("jsonwebtoken");
const config = require("../config/auth.config.js");
const db = require("../models");
const User = db.user;
const Role = db.role;
verifyToken = (req, res, next) => {
let token = req.headers["x-access-token"];
if (!token) {
return res.status(403).send({ message: "No token provided!" });
}
jwt.verify(token, config.secret, (err, decoded) => {
if (err) {
return res.status(401).send({ message: "Unauthorized!" });
}
req.userId = decoded.id;
next();
});
};
isAdmin = (req, res, next) => {
User.findById(req.userId).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
Role.find(
{
_id: { $in: user.roles }
},
(err, roles) => {
if (err) {
res.status(500).send({ message: err });
return;
}
for (let i = 0; i < roles.length; i++) {
if (roles[i].name === "admin") {
next();
return;
}
}
res.status(403).send({ message: "Require Admin Role!" });
return;
}
);
});
};
isModerator = (req, res, next) => {
User.findById(req.userId).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
Role.find(
{
_id: { $in: user.roles }
},
(err, roles) => {
if (err) {
res.status(500).send({ message: err });
return;
}
for (let i = 0; i < roles.length; i++) {
if (roles[i].name === "moderator") {
next();
return;
}
}
res.status(403).send({ message: "Require Moderator Role!" });
return;
}
);
});
};
const authJwt = {
verifyToken,
isAdmin,
isModerator
};
module.exports = authJwt;
const {auth} = require("../middlewares/authJwt"); uses destructuring, but your exports from ../middlewares/authJwt don't have a field auth.
auth therefore is undefined.

node.js passport deserializeUser not being called

In localhost, deserializeUser is being called, and there was no problem.
But after we deploy our app to ec2 using nginx(react), deserializeUser is never called.
const express = require("express");
const cors = require("cors");
const path = require("path");
const morgan = require("morgan");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const cookieParser = require("cookie-parser");
const session = require("express-session");
const passport = require("passport");
const flash = require("connect-flash");
const authRouter = require("./routes/auth");
const calendarRouter = require("./routes/calendar");
const healthPillRouter = require("./routes/healthPill");
const { sequelize } = require("./models");
const passportConfig = require("./passport");
dotenv.config();
const app = express();
sequelize
.sync()
.then(() => {
console.log("db 연결 성공");
})
.catch(console.error);
passportConfig(passport);
app.set("view engine", "pug");
app.use(morgan("combined"));
app.use(cors({ origin: "http://13.124.67.98", credentials: true }));
app.use("/", express.static(path.join(__dirname, "public")));
app.use(express.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
session({
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use("/", authRouter);
app.use("/", calendarRouter);
app.use("/", healthPillRouter);
app.listen(4000, () => {
console.log("실행중");
});
app.set("port", process.env.PORT || 8001);
// if (process.env.NODE_ENV === "production") {
// app.use(morgan("combined"));
// } else {
// app.use(morgan("dev"));
// }
app.use(express.static(path.join(__dirname, "public")));
app.use(cookieParser(process.env.COOKIE_SECRET));
const sessionOption = {
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
};
// if (process.env.NODE_ENV === "production") {
// sessionOption.proxy = true;
// sessionOption.cookie.secure = true;
// }
app.use(session(sessionOption));
app.use(flash());
this is our app.js
and the bottom is our router code.
<auth.js>
const express = require("express");
const passport = require("passport");
const bcrypt = require("bcrypt");
const { isLoggedIn, isNotLoggedIn } = require("./middlewares");
const { User, Cycle } = require("../models");
const router = express.Router();
//회원가입
router.post("/api/auth/register", isNotLoggedIn, async (req, res) => {
const {
userName,
userEmail,
userPassword,
userBirth,
userWeight,
userHeight,
firCycleStart,
firCycleEnd,
meanCycle,
meanPeriod,
userAlcohol,
} = req.body;
try {
//exUser 존재 시
const exUser = await User.findOne({ where: { userEmail } });
if (exUser) {
return res.send("이미 가입된 이메일입니다");
}
//비밀번호 암호화
const hash = await bcrypt.hash(userPassword, 12);
//users 테이블에 사용자 정보 저장
await User.create({
userName: userName,
userEmail: userEmail,
userPassword: hash,
userBirth: userBirth,
userWeight: userWeight,
userHeight: userHeight,
meanCycle: meanCycle,
meanPeriod: meanPeriod,
userAlcohol: userAlcohol,
});
const loginUser = await User.findOne({
attributes: ["id"],
where: {
userEmail: userEmail,
},
});
//시작일 정보를 입력했을 때만 주기정보 저장
if (firCycleStart) {
await Cycle.create({
bleedStart: firCycleStart,
bleedEnd: firCycleEnd,
userId: loginUser.id,
});
}
return res.status(201).json({ completed: true });
} catch (error) {
console.error(error);
return next(error);
}
});
//로그인 성공 시 json 형식으로 사용자 이름 send
router.post("/api/auth/login", isNotLoggedIn, async (req, res, next) => {
passport.authenticate("local", (authError, user, info) => {
if (authError) {
console.log(authError);
return next(authError);
}
if (!user) {
return res.send(info.message);
}
return req.login(user, (loginError) => {
if (loginError) {
console.error(loginError);
return next(loginError);
}
return res.json({id: user.id, name: user.userName});
});
})(req, res, next);
});
//로그아웃
router.get("/api/auth/logout", isLoggedIn, async (req, res) => {
console.log(req.user.id);
req.logout();
req.session.destroy();
console.log("로그아웃");
return res.status(200).send("로그아웃 되었습니다");
});
module.exports = router;
<calendar.js>
const express = require("express");
const { isLoggedIn } = require("./middlewares");
const { User, Date, Cycle } = require("../models");
const router = express.Router();
const moment = require("moment");
const Sequelize = require("sequelize");
const Op = Sequelize.Op;
//캘린더 디테일 페이지 POST
//로그인한 사용자의 id는 req.user.id로 가져올 수 있다
router.post("/api/main/date", isLoggedIn, async (req, res) => {
const {
date,
cycleStart,
cycleEnd,
isSex,
isProtection,
isControl,
dateMood,
//★ 프런트 처리 미완 ★
dateCondition,
dateMemo,
} = req.body;
try {
//사용자가 입력한 정보를 dates 테이블에 입력
//upsert 기준이 (date+userId)여야하는데 sequelize는 FK를 composite key로 사용 불가... if문 쓰는 수 밖에?
const exDate = await Date.findOne({
where: { date: date, userId: req.user.id },
});
//이미 존재하던 날짜 정보면 update
if (exDate) {
await Date.update(
{
date: date,
isSex: isSex,
isProtection: isProtection,
isControl: isControl,
dateMood: dateMood,
dateCondition1: dateCondition,
//★ 프런트 처리 미완 ★
dateCondition2: 0,
dateCondition3: 0,
dateMemo: dateMemo,
userId: req.user.id,
},
{
where: { date: date, userId: req.user.id },
}
);
} else {
//새로운 날짜 정보면 create
await Date.create({
date: date,
isSex: isSex,
isProtection: isProtection,
isControl: isControl,
dateMood: dateMood,
dateCondition1: dateCondition,
//★ 프런트 처리 미완 ★
dateCondition2: 0,
dateCondition3: 0,
dateMemo: dateMemo,
userId: req.user.id,
});
}
//사용자가 입력한 정보를 cycles 테이블에 입력
//cycleStart cycleEnd 동시에 존재하는 경우는 없게 프런트에서 처리 완료
const exCycle = await Cycle.findOne({
where: {
bleedStart: { [Op.ne]: null },
bleedEnd: null,
userId: req.user.id,
},
});
//bleedStart만 있고 bleedEnd는 없는 이전 기록이 존재하는 경우
if (exCycle) {
if (cycleStart) {
//잘못된 입력. 이전 기록의 cycleEnd를 미리 설정해야 함.
res.send("최근 생리 종료일을 먼저 입력해야 합니다.");
} else if (cycleEnd) {
//사용자가 cycleEnd를 설정: cycles 테이블 bleedEnd 업데이트
await Cycle.update(
{
bleedEnd: cycleEnd,
},
{
where: {
bleedStart: { [Op.ne]: null },
bleedEnd: null,
userId: req.user.id,
},
}
);
return res.status(200).json({ completed: true });
}
} else {
//이전 기록이 존재하지 않는 경우
if (cycleStart) {
//사용자가 cycleStart를 설정: cycles 테이블 bleedStart 저장
await Cycle.create({
bleedStart: cycleStart,
userId: req.user.id,
});
return res.status(200).json({ completed: true });
} else if (cycleEnd) {
//사용자가 cycleEnd를 설정: cycles 테이블 bleedEnd 저장, bleedStart = bleedEnd - cycles.meanPeriod로 계산 후 저장
const userInfo = await User.findOne({
attributes: ["meanPeriod"],
where: { id: req.user.id },
});
await Cycle.create({
//★ meanPeriod를 입력 안 한 사용자일때? ★
bleedStart: moment(cycleEnd, "YYYY-MM-DD")
.subtract(userInfo.meanPeriod, "d")
.format("YYYY-MM-DD"),
bleedEnd: cycleEnd,
userId: req.user.id,
});
return res.status(200).json({ completed: true });
} else {
return res.status(200).json({ completed: true });
}
}
} catch (error) {
console.error(error);
return next(error);
}
});
//캘린더 디테일 페이지 GET
//입력된 정보가 있으면 보내주고, 없으면 "입력된 정보가 없습니다."
router.get("/api/main/", isLoggedIn, async (req, res) => {
//날짜는 req.body로 받아옴
const date = req.query.Date_send;
try {
const exDate = await Date.findOne({
where: { date: date, userId: req.user.id },
});
if (exDate) {
res.send(exDate);
} else {
res.send("입력된 정보가 없습니다.");
}
} catch (error) {
console.error(error);
return next(error);
}
});
router.get("/api/main/today", isLoggedIn, async (req, res) => {
//날짜는 req.body로 받아옴
const date = req.query.Today_send;
try {
const exDate = await Date.findOne({
where: { date: date, userId: req.user.id },
});
if (exDate) {
res.send(exDate);
} else {
res.send("입력된 정보가 없습니다.");
}
} catch (error) {
console.error(error);
return next(error);
}
});
module.exports = router;
login and register have no problem, but I couldn't use any functions needed login session or cookies. How I solve this problem?
Since the release of Google Chrome 80 on February 4, 2020, the default value of Cookie's SameSite property has been changed from None to Lax.
In other words, if you send an intersection request, not the same domain address, the cookie will not work.
The solution was to change the cookie settings to sameSite none in backend app.js.
But if you change it, you have to put the attribute secure true, and it was only possible in https.
Even if it is not https, if front and backend are using the same domain, there is no problem.
I believe that applying the domain will not result in an error, because eventually you have to have a domain to apply for https

sockiet.ion passport.js, express.js and authentication headers

My chrome extension was working perfectly until recently.
I originally received a error message of
required same site none and secure in the header
I then added to my express.session config,
samesite:none, secure:true
Now instead of that error, I am unable to gain access to my website by login in with my chrome extension, which I believe is due to socket.io not maintaining the authentication cookie.
My express server is as below,
const config = require('../../config');
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server, { wsEngine: 'ws' });
const mysql = require('mysql');
const expressSession = require('express-session');
const ExpressMysqlSessionStore = require('express-mysql-session')(expressSession);
const sharedsession = require('express-socket.io-session');
const path = require('path');
const utils = require('./utils');
// remove from header "X-Powered-By: Express"
app.disable('x-powered-by');
server.listen(config.serverParams.port, config.serverParams.address, () => {
console.log(`Server running at http://${server.address().address}:${server.address().port}`);
});
/* DATABASE */
global.db = mysql.createConnection(config.db);
db.connect();
/* DATABASE */
/* SESSION */
const sessionStore = new ExpressMysqlSessionStore(config.sessionStore, db);
const session = expressSession({
...config.session,
store: sessionStore,
});
app.use(session);
/* SESSION */
app.use(express.static(config.frontendDir));
app.get([
'/signup',
'/stats',
'/pay',
], (req, res) => res.sendFile(path.join(`${config.frontendDir}${req.path}.html`)));
io.use(sharedsession(session, {
autoSave: true
}));
io.on('connection', socket => {
socket.use((packet, next) => {
if (packet[0]) {
console.log('METHOD:', packet[0]);
const sessionData = socket.handshake.session.user;
const noSessionNeed = [ 'login', 'signup', 'checkAuth' ].includes(packet[0]);
let error;
if ( ! sessionData && ! noSessionNeed) error = { code: -1, message: 'You need to login in extension!' };
if (error) return next(new Error(JSON.stringify(error)));
else next();
}
});
const auth = require('./auth')(socket);
socket.on('checkAuth', auth.checkAuth);
socket.on('login', auth.login);
socket.on('signup', auth.signup);
socket.on('logout', auth.logout);
const users = require('./users')(socket);
socket.on('users.get', users.get);
const sentiment = require('./sentiment')(socket);
socket.on('sentiment.get', sentiment.get);
socket.on('sentiment.set', sentiment.set);
socket.on('disconnect', () => {
});
});
And the config file is somewhat like this,
config.session = {
// globals.config.express.sessionSecret
resave: true,
saveUninitialized: true,
cookie: {
maxAge: 86400000,
/* FOR WORK ON LOCALHOST
secure: true,
sameSite: 'lax', */
sameSite:"None",
secure:true,
domain: '.xx.xx',
},
Here is how the authentication is done with the socket.io
const passport = require('passport');
/* PASSPORT */
require('./passport')(passport); // pass passport for configuration
/* app.use(passport.initialize());
app.use(passport.session()); */
/* PASSPORT */
const utils = require('./utils');
const bcrypt = require('bcrypt');
const saltRounds = 10;
module.exports = socket => {
this.checkAuth = fn => {
if (fn) fn();
};
this.login = (params, fn) => {
passport.authenticate('local-login', (err, user) => {
const response = {};
if (user) {
socket.handshake.session.user = user;
socket.handshake.session.save();
response.message = 'Your successful login!';
response.data = {
id: user.id,
username: user.username,
};
}
else if (err) {
response.error = {
code: err,
message: ''
};
if (err == -1) response.error.message = 'Incorrect username or password!';
}
if (fn) fn(response);
})({ body: params });
},
// socket.on('signup', (params, fn) => {
this.signup = (params, fn) => {
passport.authenticate('local-signup', (err, user) => {
const response = {};
if (user) {
console.log('signup', user);
response.message = 'Your successful signup!';
}
else if (err) {
response.error = {
code: err,
message: ''
};
if (err == -1) response.error.message = 'User alreay exist!';
}
if (fn) fn(response);
})({ body: params });
};
// socket.on('logout', fn => {
this.logout = fn => {
delete socket.handshake.session.user;
};
return this;
};
utils
module.exports = socket => {
// socket.on('users.get', fn => {
this.get = fn => {
if (fn) {
const response = {};
response.data = {
id: socket.handshake.session.user.id,
username: socket.handshake.session.user.username,
};
fn(response);
}
};
return this;
};
Would love to be able to solve this issue :P
Thanks!
This was solved by using a JWT token, separate from this, to solve the issue of the socket.io session.s
Maybe it has to do with the signup function? I think there's no sign up option for first-comers. Try making if (user) -> if (!user)

mochajs & chaijs - Uncaught TypeError: Cannot read property 'id' of undefined

I am creating an bill tracking application that is having users create bills based on criteria I have created using javascript.
I am tasked with performing acceptance testing.
This is my code so far:
My index.js file
const express = require('express')
const app = express()
const port = 3000
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/bill');
var MongoClient = require('mongodb').MongoClient
var ObjectID = require('mongodb').ObjectID
app.use(express.json())
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'))
app.set('view engine', 'pug')
app.set('views', __dirname + '/views');
var billSchema = new mongoose.Schema(
{
type: { type: String, required: true },
dueDate: { type: Date, required: true },
company: { type: String, required: true },
amtDue: { type: Number, required: true },
paidStatus: { type: String, required: true }
});
var bill = mongoose.model('bill', billSchema);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function()
{
app.get('/', (req, res) =>
{
bill.find({}, function(err, bills)
{
if (err)
{
console.log(err)
res.render('error', {})
}
else
{
res.render('index', { bills: bills })
}
});
});
app.get('/bills/new', (req, res) =>
{
res.render('bill-form', { title: "New bill", bill: {} })
});
app.get('/bills/:id/update', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.findById(id, function(err, bill)
{
if (err)
{
console.log(err)
res.render('error', {})
}
else
{
if (bill === null) {
res.render('error', { message: "Not found" })
} else {
res.render('bill-form', { title: "Update bill", bill: bill })
}
}
});
});
app.post('/bills/new', function(req, res, next) {
let newbill = new bill(req.body);
newbill.save(function(err, savedbill)
{
if (err)
{
console.log(err)
res.render('bill-form', { bill: newbill, error: err })
}
else
{
res.redirect('/bills/' + savedbill.id);
}
});
});
app.get('/bills/:id', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.findById(id, function(err, bill)
{
if (err)
{
console.log(err)
res.render('error', {})
}
else
{
if (bill === null)
{
res.render('error', { message: "Not found" })
}
else
{
res.render('bill-detail', { bill: bill})
}
}
});
});
app.post('/bills/:id/update', (req, res, next) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.updateOne({"_id": id}, { $set: req.body }, function(err, details)
{
if(err)
{
console.log(err)
res.render('error', {})
}
else
{
res.redirect('/bills/' + id)
}
});
});
app.post('/bills/:id/delete', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.deleteOne({_id: id}, function(err, product)
{
res.redirect("/")
});
});
app.post('/api/bills', (req, res) =>
{
let newbill = new bill(req.body)
newbill.save(function (err, savedbill)
{
if (err)
{
console.log(err)
res.status(500).send("There was an internal error")
}
else
{
res.send(savedbill)
}
});
});
app.post('/api/bills', (req, res) =>
{
bill.find({}, function(err, bills)
{
if(err)
{
console.log(err)
res.status(500).send("Internal server error")
}
else
{
res.send(bills)
}
});
});
app.get('/api/bills', (req, res) =>
{
bill.find({}, function(err, bills)
{
if(err)
{
console.log(err)
res.status(500).send("Internal server error")
}
else
{
res.send(bills)
}
});
});
app.get('/api/bills/:id', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.findById(id, function(err, bill)
{
if (err)
{
console.log(err)
res.status(500).send("Internal server error")
}
else
{
if (bill === null)
{
res.status(404).send("Not found")
}
else
{
res.send(bill)
}
}
});
});
app.put('/api/bills/:id', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.updateOne({"_id": id}, { $set: req.body }, function(err, details)
{
if (err)
{
console.log(err)
res.status(500).send("Internal server error")
}
else
{
res.status(204).send()
}
});
});
app.delete('/api/bills/:id', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
Review.deleteOne({"_id": id}, function(err)
{
if (err)
{
console.log(err)
res.status(500).send("Internal server error")
}
else
{
res.status(204).send()
}
});
});
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
module.exports.app = app;
module.exports.schema = bill;
Then I have a javscript dedicated to testing
let assert = require('assert');
let chai = require('chai');
let chaiHttp = require('chai-http');
let serverAndSchema = require('../index');
let server = serverAndSchema.app
let Bill = serverAndSchema.schema
let should = chai.should();
chai.use(chaiHttp);
describe('Bills', function() {
describe('/GET bill', function() {
it('should get the specified bill', function(done) {
let expectedBill = new Bill({
type: "Test Type",
dueDate: "12/3/2018T06:00:00.000Z",
company: "Test Company",
amtDue: "100",
paidStatus: "Test Status"
});
expectedBill.save(function(err, savedBill) {
chai.request(server)
.get('/api/bills/'+savedBill.id)
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('type').eql(savedBill.type)
res.body.should.have.property('dueDate').eql(savedBill.dueDate)
res.body.should.have.property('company').eql(savedBill.company)
res.body.should.have.property('amtDue').eql(savedBill.amtDue)
res.body.should.have.property('paidStatus').eql(savedBill.paidStatus)
res.body.should.have.property('_id').eql(savedBill.id)
done();
})
});
});
});
});
The data is added to my database, but I get this error when I try to run the test:
Uncaught TypeError: Cannot read property 'id' of undefined
at
C:\Users\Martae\Documents\Github\BillTracker\test\bill.js:29:46
Any help with this is appreciated!
When I checked the Bill schema, I found that the issue is caused by your due date format. So, the mongo saved is failed and you got undefined for savedBill and when you try to access id, it throws the error that you got.
Here is the solution:
let expectedBill = new Bill({
type: "Test Type",
dueDate: "2018-03-13T06:00:00.000Z", // change date to standardized format
company: "Test Company",
amtDue: "100",
paidStatus: "Test Status"
});
expectedBill.save(function(err, savedBill) {
const id = savedBill._id; // store id, it is always returned as _id
chai.request(server)
.get('/api/bills/'+id)
.end((err, res) => {
// ...
done();
});
});

How to debug "Cannot POST /" error?

I am getting this error:
Cannot POST/.
Below is the code I'm trying to execute.
Server.js
var express = require('express');
var bodyParser = require('body-parser');
var _ = require('underscore');
var db = require('./db.js');
var bcryptjs = require('bcryptjs');
var middleware = require('./middleware.js')(db);
var http = require('http').Server(app);
var app = express();
var PORT = process.env.PORT || 3000;
var todos = [];
var todoNextId = 1;
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json());
app.get('/', function(req, res) {
res.send('Todo API Root');
});
app.get('/todos', middleware.requireAuthentication, function(req, res) {
var query = req.query;
var where = {
userId: req.user.get('id')
};
if (query.hasOwnProperty('completed') && query.completed === 'true') {
where.completed = true;
} else if (query.hasOwnProperty('completed') && query.completed === 'false') {
where.completed = false;
}
if (query.hasOwnProperty('q') && query.q.length > 0) {
where.description = {
$like: '%' + query.q + '%'
};
}
db.todo.findAll({
where: where
}).then(function(todos) {
res.json(todos);
}, function(e) {
res.status(500).send();
});
});
app.get('/todos/:id', middleware.requireAuthentication, function(req, res) {
var todoId = parseInt(req.params.id, 10);
db.todo.findOne({
where: {
id: todoId,
userId: req.user.get('id')
}
}).then(function(todo) {
if (!!todo) {
res.json(todo.toJSON());
} else {
res.status(404).send();
}
}, function(e) {
res.status(500).send();
});
});
app.post('/todos', middleware.requireAuthentication, function(req, res) {
var body = _.pick(req.body, 'description', 'completed');
db.todo.create(body).then(function(todo) {
req.user.addTodo(todo).then(function () {
return todo.reload();
}).then(function (todo) {
res.json(todo.toJSON());
});
}, function(e) {
res.status(400).json(e);
});
});
app.delete('/todos/:id', middleware.requireAuthentication, function(req, res) {
var todoId = parseInt(req.params.id, 10);
db.todo.destroy({
where: {
id: todoId,
userId: req.user.get('id')
}
}).then(function(rowsDeleted) {
if (rowsDeleted === 0) {
res.send(404).json({
error: 'No todo with id'
});
} else {
res.status(204).send();
}
}, function() {
res.status(500).send();
});
});
app.put('/todos/:id', middleware.requireAuthentication, function(req, res) {
var todoId = parseInt(req.params.id, 10);
var body = _.pick(req.body, 'description', 'completed');
var attributes = {};
if (body.hasOwnProperty('completed')) {
attributes.completed = body.completed;
}
if (body.hasOwnProperty('description')) {
attributes.description = body.description;
}
db.todo.findOne({
where: {
id: todoId,
userId: req.user.get('id')
}
}).then(function(todo) {
if (todo) {
todo.update(attributes).then(function(todo) {
res.json(todo.toJSON());
}, function(e) {
res.status(400).json(e);
});
} else {
res.status(404).send();
}
}, function() {
res.status(500).send();
});
});
app.post('/users', function(req, res) {
var body = _.pick(req.body, 'email', 'password');
db.user.create(body).then(function(user) {
res.json(user.toPublicJSON());
}, function(e) {
res.status(400).json(e);
});
});
app.post('/users/login', function (req, res) {
var body = _.pick(req.body, 'email', 'password');
var userInstance;
db.user.authenticate(body).then(function (user) {
var token = user.generateToken('authentication');
userInstance = user;
return db.token.create({
token: token
});
}).then(function (tokenInstance) {
res.header('Auth',
tokenInstance.get('token')).json(userInstance.toPublicJSON());
}).catch(function () {
res.status(401).send();
});
});
app.delete('/users/login', middleware.requireAuthentication,
function (req, res) {
req.token.destroy().then(function () {
res.status(204).send();
}).catch(function () {
res.status(500).send();
});
});
db.sequelize.sync({force: true}).then(function() {
app.listen(PORT, function() {
console.log('Express listening on port ' + PORT + '!');
});
});
This is my app.js file
app.post('/users', function(req, res) {
var body = _.pick(req.body, 'email', 'password');
db.user.create(body).then(function(user) {
res.json(user.toPublicJSON());
}, function(e) {
res.status(400).json(e);
});
});
I've been trying this but not getting through.Not sure whether the html file I have is correct. Want to create an html file to post from, but mine is refusing to respond.
You cannot POST to / because you haven't defined a route handler for POST requests to / (you only have one for GET to /).

Categories

Resources