Стек MERN, явная ошибка — «Ошибка типа: не удается прочитать свойство ‘_id’ неопределенного» в apiroutes

#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/