#javascript #node.js #mongodb #api #express
#javascript #node.js #mongodb #API #экспресс
Вопрос:
Я запускаю приложение стека MERN. У меня есть две коллекции. «Пользователи» и «Подписка». Я получаю эту ошибку, когда регистрирую пользователя, а затем пытаюсь добавить подписку.
TypeError: Cannot read property '_id' of undefined
[0] at /Users/njboot/web-development/submarine/routes/apiroutes.js:72:45
Пользователь успешно добавлен в коллекцию «User» базы данных после регистрации. Если я снова выхожу из системы, а затем снова вхожу, я могу добавлять подписки. Я просто не могу добавлять подписки, если я зарегистрируюсь сначала (в первом сеансе).
Я пытался использовать body-parser
промежуточное программное обеспечение вместо express на всякий случай, если это была проблема, но это не так.
Вот мой express-config.js
:
require("dotenv").config();
// SET EXPRESS ENVIRONMENT
const express = require("express");
const app = express();
// const path = require("path")
// imports session, logger, passport, and path
const middleware = require("../middleware");
// Define middleware here
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
// ADD WINSTON LOGGER MIDDLEWARE TO SERVER
app.use(middleware.logger);
// We need to use sessions to keep track of our user's login status
app.use(
middleware.session({
secret: "sandwich",
resave: true,
saveUninitialized: true,
})
);
app.use(middleware.passport.initialize());
app.use(middleware.passport.session());
// Serve up static assets (usually on heroku)
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"));
}
require("../routes/apiroutes")(app);
module.exports = app;
Вот мой apiroutes.js
, я сделал комментарий в строке 72, где я получаю ошибку:
const middleware = require("../middleware");
const passport = middleware.passport;
const User = require("../models/User");
const API = require("../controller");
const path = require("path");
const scrubUser = userObject => {
let cleanUser = {};
cleanUser.subscriptions = userObject.subscriptions;
cleanUser.firstname = userObject.firstname;
cleanUser.lastname = userObject.lastname;
cleanUser.email = userObject.email;
cleanUser.income = userObject.income;
return cleanUser;
};
module.exports = app => {
// Endpoint to login
app.post("/login", passport.authenticate("local"), (req, res) => {
try {
API.controller.getUser(req.user._id, response => {
return res.json(scrubUser(response));
});
} catch (err) {
throw err;
}
});
app.get("/logout", (req, res) => {
req.logout();
res.send({ result: "success" });
});
// Register User
app.post("/register", (req, res) => {
var password = req.body.password;
var password2 = req.body.password2;
if (password == password2) {
var newUser = new User({
name: req.body.name,
firstname: req.body.firstname,
lastname: req.body.lastname,
email: req.body.email,
income: req.body.income,
username: req.body.username,
password: req.body.password,
});
User.createUser(newUser, (err, user) => {
if (err) throw err;
res.send(user).end();
});
} else {
res.status(500).send('{ errors: "Passwords don't match" }').end();
}
});
// Endpoint to get current user
app.get("/api/getuser", (req, res) => {
if (!req.user) return res.json({ result: "no user" });
try {
API.controller.getUser(req.user._id, response => {
return res.json(scrubUser(response));
});
} catch (err) {
throw err;
}
});
app.post("/api/addsub", (req, res) => {
// I GET THE ERROR HERE!
API.controller.addSubscription(req.user._id, req.body, response => {
try {
API.controller.getUser(req.user._id, response => {
return res.json(scrubUser(response));
});
} catch (err) {
throw err;
}
});
});
app.post("/api/removesub", (req, res) => {
API.controller.removeSubscription(req.user._id, req.body.id, response => {
try {
API.controller.getUser(req.user._id, response => {
return res.json(scrubUser(response));
});
} catch (err) {
throw err;
}
});
});
app.all("*", function (req, res) {
res.redirect("https://submarine-sub-tracker.herokuapp.com/");
});
};
Вот мой controller
:
var mongojs = require("mongojs");
const db = require("../models");
const Controller = {
getUser: (id, callback) => {
db.User.findOne({ _id: mongojs.ObjectId(id) })
.populate("subscriptions")
.then(theUser => callback(theUser));
},
addSubscription: (userId, newSub, callback) => {
console.log(userId);
db.Subscription.create(newSub).then(response => {
db.User.findOneAndUpdate(
{ _id: mongojs.ObjectId(userId) },
{ $push: { subscriptions: response._id } },
{ new: true }
).then(theUser => callback(theUser));
});
},
removeSubscription: (userId, subId, callback) => {
db.User.findOneAndUpdate(
{ _id: mongojs.ObjectId(userId) },
{ $pull: { subscriptions: mongojs.ObjectId(subId) } },
{ new: true }
).then(theUser => callback(theUser));
},
};
module.exports = Controller;
И, наконец, мой server.js
:
require("dotenv").config();
const app = require("./config/express-config");
const mongoose = require("mongoose");
const PORT = process.env.PORT || 5000;
const MONGODB_URI =
process.env.MONGODB_URI ||
`mongodb srv://root:${process.env.PASSWORD}@cluster0.6e0yo.mongodb.net/submarine?retryWrites=trueamp;w=majority`;
// connect to MongoDB
mongoose.connect(MONGODB_URI, { useNewUrlParser: true }, err => {
if (err) {
console.log("There is a problem with the connection" err);
} else {
console.log("Mongoose connection is good.");
console.log(MONGODB_URI);
}
});
//server is up and running
app.listen(PORT);
Здесь также приведена конфигурация паспорта:
var passport = require("passport");
var LocalStrategy = require("passport-local").Strategy;
var User = require("../models/User");
passport.use(
new LocalStrategy(function (username, password, done) {
User.getUserByUsername(username, function (err, user) {
if (err) throw err;
if (!user) {
return done(null, false, { message: "Unknown User" });
}
User.comparePassword(password, user.password, function (err, isMatch) {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: "Invalid password" });
}
});
});
})
);
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
console.log(req.user);
User.getUserById(id, function (err, user) {
done(err, user);
});
});
// Exporting our configured passport
module.exports = passport;
Комментарии:
1. Поскольку ошибка говорит, что ваш _id не определен. В вашем контроллере api
console.log(req.user)
и сообщите нам, что вы получаете2. @HenryLy Итак, я
console.log(req.user)
addSubscription
использую метод контроллера, и в консоли ничего не появляется. Я предполагаю, что оно никогда не достигается?3. @
console.log(userId)
HenryLy ничего не возвращает4. привет, @njboot, откуда запрос.user получает его значение? Возможно, вы забыли добавить промежуточное программное обеспечение.
5. @HenryLy Я считаю, что паспорт
Ответ №1:
Вы, очевидно, неправильно настроили passport.
https://www.sitepoint.com/local-authentication-using-passport-node-js/