I tried using Populate in mongoose but it didn't work - node.js

Hello everyone i am in a problem, may be you can help me.
So basically i have created two collection in mongoose, one for user details when they sign Up or login and other for Recipe they post.
I also want to save the each recipe a user post in the user collection (like populate property of mongoose). like if user1 post a recipe1 then it should save in the recipe collection and also in the user data who posted this.
I tried to use Populate method for this as shown in the code below but when ever i post some recipe it stored in recipe collection only and the "posts" key in the users collection is always empty. I want to save the recipe in the "posts" key of the users collection also.
Please Guide me how to do this.
require('dotenv').config()
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const requestObj = require("request");
const https = require("https");
const multer = require("multer");
const path = require("path");
const mongoose = require('mongoose');
const session = require('express-session');
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const findOrCreate = require('mongoose-findorcreate');
const app = express();
const GoogleStrategy = require('passport-google-oauth20').Strategy;
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static("public"));
app.use(session({
secret: "This is my secret",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
// Mongoose connection
mongoose.connect("mongodb://localhost:27017/recipeUsers", {
useNewUrlParser: true,
useUnifiedTopology: true
});
mongoose.set('useCreateIndex', true);
//mongoose schema
const userSchema = new mongoose.Schema({
username: String,
password: String,
googleId: String,
name: String,
posts: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Recipe'
}]
});
const recipeSchema = new mongoose.Schema({
genre: String,
name: String,
description: String,
ingredients: [{
type: String
}],
method: [{
type: String
}],
imageName: String,
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
// model
const Recipe = mongoose.model("Recipe", recipeSchema);
const User = mongoose.model("User", userSchema);
module.exports = {
User,
Recipe,
}
passport.use(User.createStrategy());
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use(new GoogleStrategy({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL: "http://localhost:5000/auth/google/index",
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
function(accessToken, refreshToken, profile, cb) {
// console.log(profile);
User.findOrCreate({
googleId: profile.id,
name: profile.displayName
}, function(err, user) {
return cb(err, user);
});
}
));
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "public/img/uploads")
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
var upload = multer({
storage: storage,
limits: {
fileSize: 5 * 1024 * 1024
}
});
app.use((req, res, next) => {
res.locals.isAuthenticated = req.isAuthenticated();
if (req.isAuthenticated()) {
currentUser = req.user.name;
}
next();
});
app.get("/", function(req, res) {
res.render("index");
});
app.get("/index", (req, res) => {
res.render('index');
});
app.get("/about", function(req, res) {
res.render("about");
});
app.route("/search")
.get(function(req, res) {
res.render("search");
})
.post(function(req, res) {
const searchRecipe = req.body.recipeName;
Recipe.findOne({
name: searchRecipe
}, (err, foundRecipe) => {
if (err) {
res.send(err);
} else {
if (foundRecipe) {
res.render("recipe", {
dishName: foundRecipe.name,
descrip: foundRecipe.description,
genre: foundRecipe.genre,
ingredients: foundRecipe.ingredients,
steps: foundRecipe.method,
author: foundRecipe.author,
dishImage: foundRecipe.imageName
});
} else {
res.redirect("/Failure");
}
}
});
});
app.get("/Failure", function(req, res) {
res.render("Failure");
});
app.route("/post")
.get(function(req, res) {
if (req.isAuthenticated()) {
res.render("post", {
message: ""
});
} else {
res.redirect("/login");
}
})
.post(upload.single('dishImage'), function(req, res, next) {
const dishType = req.body.recipeGenre;
const description = req.body.description;
const dishName = req.body.dishName;
const ingredient = req.body.ingredients;
const step = req.body.steps;
// const authorName = req.body.author;
// const url = "https://polar-oasis-10822.herokuapp.com/recipes";
const file = req.file;
if (!file) {
const error = new Error("Please upload a image");
error.httpStatusCode = 400;
return next(error);
}
// console.log(req.user);
const dish = new Recipe({
genre: dishType,
name: dishName,
description: description,
ingredients: ingredient,
method: step,
imageName: file.filename,
});
dish.save((err) => {
if (err) {
res.send(err);
} else {
User.findOne({
_id: req.user._id
})
.populate('posts').exec((err, posts) => {
console.log("Populated User " + posts);
})
res.render("post", {
message: "Your Recipe is successfully posted."
});
}
});
});
app.get("/menu", function(req, res) {
res.render("menu");
});
app.get('/auth/google',
passport.authenticate('google', {
scope: ["profile"]
})
);
app.get('/auth/google/index', passport.authenticate('google', {
failureRedirect: '/login'
}), function(req, res) {
// Successful authentication, redirect home.
res.redirect('/');
});
app.get("/logout", (req, res) => {
req.logout();
res.redirect('/');
});
app.route("/signup")
.get((req, res) => {
res.render("signup");
})
.post((req, res) => {
User.register({
username: req.body.username,
name: req.body.name,
}, req.body.password, (err, user) => {
if (err) {
console.log(err);
res.redirect("/signup");
} else {
passport.authenticate("local")(req, res, () => {
res.redirect('/');
});
}
});
})
app.route("/login")
.get((req, res) => {
res.render("login");
})
.post((req, res) => {
const user = new User({
username: req.body.username,
password: req.body.password
});
req.login(user, (err) => {
if (err) {
console.log(err);
} else {
passport.authenticate("local")(req, res, () => {
res.redirect("/");
});
}
});
})
app.listen(process.env.PORT || 5000, function() {
console.log("server is running on port 5000");
});

I believe your problem is here:
dish.save((err) => {
if (err) {
res.send(err);
} else {
User.findOne({
_id: req.user._id
})
.populate('posts').exec((err, posts) => {
console.log("Populated User " + posts);
})
res.render("post", {
message: "Your Recipe is successfully posted."
});
}
});
});
You are using populate as a function that changes the dataset elements, but it is just a trick for printing results from different collection, in the roots, they are different; if you want them to be in the same document, you must use subdocuments. populate does not change document paths.
Assuming I have not typed anything wrong, that you must correct yourself or let me know, this should solve your problem; just use populate to print the documents our as one, not to save.
app
.route("/post")
.get(function(req, res) {
if (req.isAuthenticated()) {
res.render("post", {
message: ""
});
} else {
res.redirect("/login");
}
})
.post(upload.single("dishImage"), function(req, res, next) {
const dishType = req.body.recipeGenre;
const description = req.body.description;
const dishName = req.body.dishName;
const ingredient = req.body.ingredients;
const step = req.body.steps;
const username = req.body.author; //make sure this information is passed to req.body
// const url = "https://polar-oasis-10822.herokuapp.com/recipes";
const file = req.file;
if (!file) {
const error = new Error("Please upload a image");
error.httpStatusCode = 400;
return next(error);
}
// console.log(req.user);
const dish = new Recipe({
genre: dishType,
name: dishName,
description: description,
ingredients: ingredient,
method: step,
imageName: file.filename
});
dish.save(err => {
if (err) {
res.send(err);
} else {
User.findOne({
_id: req.user._id
}).then(user => {//I have changed just here! I have eliminated the populate call
user.posts.push(dish._id);
user.save().then(() => {
console.log("okay");
});
});
res.render("post", {
message: "Your Recipe is successfully posted."
});
}
});
});
Since your code is big, I may have missed something, please, let me know if I have misunderstood what you wanted.
References
https://mongoosejs.com/docs/populate.html#refs-to-children

Related

ensureAuthenticated midddleware not correctly authenticating

a user login successfully and redirected to profile was implemented with success.but, when i try to access a new route by requesting http://localhost:5000/user/admin/request/newAdmin route the authentication middleware responses with You are not authorized to view this page after login why is that???
server.js
require("dotenv").config();
const express = require("express");
const app = express();
// const flash = require("connect-flash");
const session = require("express-session");
const passport = require("passport");
const mongoose = require("mongoose");
const MongoStore = require("connect-mongo");
const cors = require("cors");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
// app.use(flash());
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: true,
saveUninitialized: true,
store: MongoStore.create({
mongoUrl: process.env.DB,
collection: "sessions",
}),
cookie: { secure: false, maxAge: 1000 * 60 * 60 * 24 * 3 },
})
);
app.use(passport.initialize());
app.use(passport.session());
mongoose
.connect(process.env.DB)
.then(() => {
console.log("DB connection successful");
})
.catch((err) => {
console.log(`DB connection Error: ${err}`);
});
const userRouter = require("./routes/userRoutes");
app.use("/user", userRouter);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`server is running on port ${PORT}`);
});
module.exports = app;
userRoutes.js
const router = require("express").Router();
const passport = require("passport");
const { ObjectID } = require("mongodb");
const LocalStrategy = require("passport-local");
const bcrypt = require("bcrypt");
const crypto = require("crypto");
const Token = require("../models/token");
const sendEmail = require("../utils/sendEmail");
const User = require("../models/userModel.js");
router.route("/register").post(
(req, res, next) => {
User.findOne({ fullName: req.body.fullName }, (err, user) => {
if (err) {
next(err);
} else if (user) {
res.json({ user: "user with that name already exists!" });
} else {
const {
fullName,
email,
userType,
department,
stream,
id,
batch,
phoneNumber,
password,
} = req.body;
const hash = bcrypt.hashSync(password, 12);
console.log(hash);
if(userType === "Admin"){
User.find({ userType: "Admin" }, (err, users) => {
if (err) console.log(err);
if(users.length === 0 ){
const newUser = new User({
fullName,
email,
userType,
department,
stream,
id,
batch,
phoneNumber,
password: hash,
});
newUser.save((err, data) => {
if (err) console.log(err);
next(null, data);
});
}else{
const newUser = new User({
fullName,
email,
userType,
department,
stream,
id,
batch,
phoneNumber,
password: hash,
approved: false
});
newUser.save((err, data) => {
if (err) console.log(err);
next(null, data);
})
}
})
}else{
const newUser = new User({
fullName,
email,
userType,
department,
stream,
id,
batch,
phoneNumber,
password: hash,
});
newUser.save((err, data) => {
if (err) console.log(err);
next(null, data);
});
}
}
});
},
passport.authenticate("local", { failureRedirect: "/" }),
(req, res, next) => {
const userAuth = req.user.fullName;
if (userAuth) {
User.findOne({ fullName: userAuth }, (err, user) => {
if (err) console.log(err);
const userPriv = user.userType;
if(userPriv === "Student"){
return res.json({ user: user.fullName ,identity: {id: "Student"}});
}
else if(userPriv === "Admin"){
if(user.approved){
return res.json({ user: user.fullName , identity: {id: "Admin",approved: true} });
}
return res.json({ user: user.fullName , identity: {id: "Admin",approved: false} });
}else{
return res.json({ user: user.fullName , identity: {id: "Teacher"} });
}
});
} else {
res.sendStatus(401).json({ user: "Incorrect password or email" });
}
}
);
router.route("/login").post(passport.authenticate("local"), (req, res) => {
const userAuth = req.user.fullName;
console.log(req.user);
if (userAuth) {
User.findOne({ fullName: userAuth }, (err, user) => {
if (err) console.log(err);
const userPriv = user.userType;
if(userPriv === "Student"){
return res.json({ user: user.fullName ,identity: {id: "Student"}});
}
else if(userPriv === "Admin"){
if(user.approved){
return res.json({ user: user.fullName , identity: {id: "Admin",approved: true} });
}
return res.json({ user: user.fullName , identity: {id: "Admin",approved: false} });
}else{
return res.json({ user: user.fullName , identity: {id: "Teacher"} });
}
});
} else {
res.sendStatus(401).json({ user: "Incorrect password or email" });
}
});
router.route("/admin/request/newAdmin").get(ensureAuthenticated,(req, res) => {
User.find({userType: "Admin", approved: false},(err,users) => {
if (err) console.log(err);
res.json({users});
})
});
router.route("/logout").get((req, res, next) => {
req.logout(function (err) {
if (err) {
return next(err);
}
console.log("the user has logged out!");
res.json({ user: "logout success!" });
});
});
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
User.findOne({ _id: new ObjectID(id) }, (err, doc) => {
done(null, doc);
});
});
const customFields = {
usernameField: "email",
};
passport.use(
new LocalStrategy(customFields, (email, password, done) => {
User.findOne({ email }, (err, user) => {
console.log(`User ${user.email} attempted to log in.`);
if (err) return done(err);
if (!user) return done(null, false);
if (!bcrypt.compareSync(password, user.password)) {
return done(null, false);
}
return done(null, user);
});
})
);
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
console.log(req.isAuthenticated());
console.log(req.user);
res.redirect("/user/err");
}
router.route("/err").get((req,res) => {
res.status(401).json({ msg: "You are not authorized to view this page" });
})
module.exports = router;
i was expecting for the ensureAuthenticated middleware to respond with authenticated because the user is logged in.but one thing i noticed is when i console logged req.user in the login route it set it to the current user object but in the ensureAuthenticated middleware it is undefined even if the user has not logged out.why is that?may be am i wrong when initializing the session and passport in server.js?

Client doesnt get cookie from my node.js api

I have made an authentication with jwt api in node.js/express and i run it on heroku.
When a user logged in, server create a cookie via cookie-parser and send it to the client.
Below is the code from server.js
const express = require('express');
const jwt = require('jsonwebtoken');
const cookieParser = require('cookie-parser');
const cors = require('cors');
const path = require('path');
const bcrypt = require('bcrypt');
const PORT = process.env.PORT || 3000;
const serveStatic = require('serve-static');
require('dotenv').config();
const mongoose = require('mongoose');
const { User, Posts } = require(path.join(__dirname, './model.js'));
const mongoString = process.env.DATABASE_URL;
const JWT_SECRET = process.env.JWT_SECRET;
const { verifyToken, checkUser } = require(path.join(__dirname, './auth.js'));
const app = express();
//Middlewares
app.use(
cors({
credentials: true,
origin: true,
})
);
app.use(express.json());
app.use(cookieParser());
//Connect to Database
mongoose.connect(mongoString);
const db = mongoose.connection;
db.on('error', (err) => {
console.log(err);
});
db.once('connected', () => {
console.log('----Database Connected----\n');
});
//functions
const maxAge = 3 * 24 * 60 * 60;
const createToken = (id) => {
return jwt.sign({ id }, JWT_SECRET, {
expiresIn: maxAge,
});
};
// AUTH ROUTES
app.get('*', checkUser);
app.get('/', checkUser, (req, res) => {
res.json({ status: 'success' });
});
app.post('/api/register', async (req, res) => {
const salt = await bcrypt.genSalt();
try {
const user = await User.create(
new User({
username: req.body.username,
email: req.body.email,
city: req.body.city,
password: await bcrypt.hash(req.body.password, salt),
})
);
const token = createToken(user._id);
res.cookie('jwt', token, {
maxAge: maxAge * 1000,
secure: true,
});
res.status(201).json(user);
console.log(user);
} catch (err) {
console.log(err);
res.json(err);
}
});
app.post('/api/login', async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email }).lean();
if (!user) {
return res.send({
status: 'error',
error: 'Invalid email',
});
}
if (await bcrypt.compare(password, user.password)) {
const token = createToken(user._id);
res.cookie('jwt', token, { secure: true, maxAge: maxAge * 1000 });
res.status(200).send({ status: 'ok', token: token });
console.log(user._id + ' logged in successfully');
return;
}
return res.send({ status: 'error', error: 'Invalid password' });
} catch (err) {
console.log(err);
}
});
app.get('/api/home', verifyToken, (req, res) => {
res.send(res.locals.user);
});
app.get('/api/logout', (req, res) => {
try {
res.cookie('jwt', '', { maxAge: 1 });
res.status(200).send({ status: 'ok' });
} catch (err) {
res.send(err);
}
});
//POSTS ROUTES
app.post('/api/posts', verifyToken, checkUser, async (req, res) => {
try {
const post = await Posts.create(
new Posts({
postBody: req.body.postBody,
city: req.body.city,
author: res.locals.user.id,
})
);
res.status(200).json(post);
console.log('====New Post=====');
} catch (err) {
res.status(400).send({ message: err.message });
}
});
app.get('/api/posts', verifyToken, async (req, res) => {
try {
const data = await Posts.find();
res.send({ user: res.locals.user, data: data });
} catch (err) {
res.json({ message: err.message });
}
});
app.get('/api/posts/:city', verifyToken, async (req, res) => {
try {
const data = await Posts.find({ city: req.params.city });
res.json(data);
res.send(res.locals.user);
} catch (err) {
res.json({ message: err.message });
}
});
//run server
app.listen(PORT, () => {
console.log(`Server running on ${PORT}...\n`);
});
Now, for front-end i use Vue.js that its running on Firebase.
Here is the script part of Login.Vue
<script>
/* eslint-disable */
import axios from 'axios';
export default {
name: 'Login',
data() {
return {
email: '',
password: '',
error: '',
};
},
methods: {
async onSubmit() {
if (!this.email || this.password.length < 6) {
this.error = 'vale kati';
return;
}
await axios
.post(
'https://thelostpet.herokuapp.com/api/login',
{
email: this.email,
password: this.password,
},
{ withCredentials: true }
)
.then((res) => {
console.log(res.data.token);
if (res.data.status == 'error') {
this.error = res.data.error;
}
if (res.data.status == 'ok') {
this.$router.push('/home');
}
})
.catch((err) => {
console.log(err);
});
},
},
};
</script>
When I try to login from Login.vue, that its ruuning on Firebase, the browser doesn't save the cookie that it created from the api.
BUT when I make a post request on https://thelostpet.herokuapp.com/api/login from postman, the cookie is saved on postman.
Thank you!

400 Bad Request in NodeJs Application

When ever I submit a from to login in or get registered I get 400 bad request. But in register route the user get registered but it also gives bad request. When we go to login route same as register route I get BAD REQUEST. 0
I am using the following dependencies:
express session
passport
passport-local
passport-local-mongoose
Is there something wrong with the implementation of the passport-local-mongoose or its passport side or serialize or deserialize the user. Can anybody help me with this problem I am stuck on this for three days. Here is some code.
//-----------------------//Require---------------------
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const ejs = require("ejs");
const session = require("express-session");
const passport = require("passport");
const LocalStrategy= require("passport-local").Strategy;
const passportLocalMongoose = require("passport-local-mongoose");
const mongoose = require("mongoose");
//-----------------------//App.use---------------------
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
//-----------------------//Passport---------------------
app.use(passport.initialize());
app.use(passport.session());
//-----------------------//Mongoose---------------------
mongoose.connect('mongodb://localhost/Twitter', {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.set('useCreateIndex', true);
const tweetschema = new mongoose.Schema({
username: String,
password: String,
tweets: String
});
//-----------------------//Schema Plgin---------------------
tweetschema.plugin(passportLocalMongoose);
//-----------------------//New Model---------------------
const Tweet = new mongoose.model("Tweet", tweetschema);
//-----------------------//Local Strategy-------------------
passport.use(new LocalStrategy(Tweet.authenticate()));
//-----------------------//Seralize Passport---------------------
passport.serializeUser(Tweet.serializeUser());
passport.deserializeUser(Tweet.deserializeUser());
//-----------------------//Get Routes---------------------
app.get("/" ,(req, res)=>{
Tweet.find({}, function(err, founItems){
res.render("home", {founItems:founItems});
});
});
app.get("/tweets", (req, res)=>{
if(req.isAuthenticated()){
res.render("Tweets");
}else{
res.redirect("/login");
}
});
//-----------------------//Post Routes---------------------
app.post("/login", (req, res)=>{
const user = new Tweet({
username: req.body.email,
password: req.body.password
});
req.logIn(user, (err)=>{
if(err){
res.send(err);
}
passport.authenticate("local")(req, res, ()=>{
console.log("Successfull.");
})
})
});
app.post("/reg", (req, res)=>{
Tweet.register({username: req.body.email}, req.body.password, (err, user)=>{
if(err){
console.log(err);
res.redirect("/reg");
}else{
if(user){
passport.authenticate("local")(req, res, ()=>{
res.redirect("/tweets");
console.log("Successfully Regsitered The User!");
})
}
}
})
})
You redirect user to /login route, but you don't have get request for this.
If you have it but not uploaded try this in Seralize Passport
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
What about this:
app.post("/login", (req, res) => {
const email = req.body.email;
User.findOne({ username: email }, function (err, u) {
if (err) {
console.log(err);
} else {
if (u) {
u.authenticate(req.body.password, (err, model, info) => {
if (info) {
res.send("Wrong email or password!");
}
if (err) {
console.log(err);
} else if (model) {
req.login(u, (err) => {
if (err) {
console.log(err);
} else {
passport.authenticate("local");
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
}
});
}
});
} else {
res.send("Wrong email or password!");
}
}
});
});
So you first search user in the database with email: User.findOne({ username: email }, function (err, u){} I suggest to make username unique username: { type: String, unique: true} in tweetSchema.
After that you check for err. If u exists, you authenticate it with password. According to passport-local-mongoose- u.authenticate(password, (err, model, info)=>{}) has two arguments: password and callback function. In callback we check for info which is "an instance of AuthenticationError describing the reason the password failed, else undefined." After that we check for err and it is "null unless the hashing algorithm throws an error." And finally, we check for model that is "the model getting authenticated if authentication was successful otherwise false."
So, model is authenticated. After that we must use the user with req.login(u,(err)). Check for errors and if everything is alright, we authenticate user locally passport.authenticate("local");. If you want to save session, write:
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
That's all.
For registration :
app.post("/register", (req, res) => {
const email = req.body.email;
const password = req.body.password
User.find({ email: email }, function (err, docs) {
if (docs.length === 0) {
User.register(
{
username: email,
},
password,
function (err, user) {
if (err) {
console.log(err);
} else {
req.login(user, (err) => {
if (err) {
console.log(err);
} else {
passport.authenticate("local");
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
}
});
}
}
);
} else {
res.send("The accout already exists!");
}
});
});

How to Append key: value pairs to existing Mongodb objects using Mongoose

const express = require('express');
const bcrypt = require('bcryptjs');
const passport = require('passport');
const { ensureAuthenticated } = require('../config/auth');
const router = express.Router();
//User/Post model
const User = require('../models/DBmusevista');
//Welcome/register page
router.get('/', (req, res) => res.render('register'));
//Login page
router.get('/login', (req, res) => res.render('login'));
//Home page
router.get('/home', ensureAuthenticated, (req, res) => res.render('home', {user_mv: req.user}));
//Create topic page
router.get('/create-topic', ensureAuthenticated, (req, res) => res.render('create-topic', {user_mv: req.user}));
//Register handle
router.post('/', (req, res) => {
const {firstname, lastname, username, email, password} = req.body;
let errors =[];
if(!firstname || !lastname || !username || !email || !password) {
errors.push({msg: 'Please check all fields.'});
};
//Check password length
if(password.length < 6) {
errors.push({msg: 'Password should be at least 6 characters.'});
};
if(errors.length > 0){
res.render('register', {
errors,
firstname,
lastname,
username,
email,
password
});
}else {
//Validation passed
User.findOne({email: email})
.then(user => {
if(user){
//User exists
errors.push({msg: 'Email is already registered.'})
res.render('register', {
errors,
firstname,
lastname,
username,
email,
password
});
} else {
const newUser = new User({ //Check User
firstname,
lastname,
username,
email,
password
});
//Hash password
bcrypt.genSalt(10, (err, salt) =>
bcrypt.hash(newUser.password,salt, (err, hash) => {
if(err) throw err;
//Set password to hash
newUser.password = hash;
//Save user
newUser.save()
.then(user => {
req.flash('success_msg', 'You are now registered and can now log in');
res.redirect('/login');
})
.catch(err => console.log(err));
}))
}
});
}
});
//Post handle
router.post('/create-topic', (req, res) => {
let newObj = {
title: req.body.title,
category: req.body.category,
vista: req.body.vista,
description: req.body.description
}
User.updateOne({username: user_mv.username}, { $set: {post: newObj}});
res.send('Hello');
//This is the code that does not work. Anything else I've tried has not worked.
});
//Login handle
router.post('/login', (req, res, next) => {
passport.authenticate('local', {
successRedirect: '/home',
failureRedirect: '/login',
failureFlash: true
})(req, res, next);
});
module.exports = router;
const mongoose = require('mongoose');
const DBmusevistaSchema = mongoose.Schema({
firstname: {
type: String,
required: false
},
lastname: {
type: String,
required: false
},
username: {
type: String,
required: false
},
email: {
type: String,
required: false
},
password: {
type: String,
required: false
},
date: {
type: Date,
default: Date.now
}
});
const DBmusevista = mongoose.model('DBmusevista', DBmusevistaSchema);
module.exports = DBmusevista;
When an individual comes to my website the beginning page ('/') is a registration for for my site. I have a post request for my MongoDB collection that creates a 'user register' object (fname, lname, username, email, pass). Once logged in ('/home') a user can then create a new post(s) form that is located in my create-topic.ejs file('/create-topic'). I'm new to using MongoDB so my question is how can I append the post submitted (title, category, vista, description) to an array for the users' object.
I'm not sure if I should add an array (posts: []) to DBmusevistaSchema and create a Post.Schema({key: value}) in my DBmusevista file? I tried using User.findOne but I cannot get it to work. Please help.
try {
const pirs = await Pir.find();
pirs.forEach(async (pir) => {
let pir2 = new Pir();
pir.isSubmitted = false;
pir2 = pir;
const out = await pir2.save();
console.log(out);
});
} catch (err) {
next(err);
}

Node.js > 'findOne' of undefined < LocalStrategy from Passport

I used Passport to create login.
However, I get:
TypeError: Cannot read property 'findOne' of undefined
when trying to login.
After debugging, I confirmed that user was undefined after async of localStrategy.js.
I think all the actions are perfect, but there is a problem with my code.
Can I tell you where I made the mistake?
passport/index.js
const local = require('./localStrategy');
const { User } = require('../model/user');
module.exports = (passport) => {
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
User.findOne({ id: id })
.then((user) => done(null, user))
.catch((err) => done(err));
});
local(passport);
};
passport/localStrategy.js
const LocalStrategy = require('passport-local').Strategy;
const { User } = require('../model/user');
module.exports = (passport) => {
passport.use(
new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password'
},
async (email, password, done) => {
try {
const exUser = await User.findOne({ email: email });
if (exUser) {
const result = await bcrypt.compare(password, exUser.password);
if (result) {
done(null, exUser);
} else {
done(null, false, { message: 'failed.' });
}
} else {
done(null, false, { message: 'failed.' });
}
} catch (err) {
console.error(err);
done(err);
}
}
)
);
};
routes/user.js
const express = require('express');
const router = express.Router();
const { isLoggedIn, isNotLoggedIn } = require('./middleware');
const usersController = require('../controller/users_controller');
router.get('/login', isNotLoggedIn, usersController.user_login);
controller/users_controller.js
const User = require('../model/user');
const bcrypt = require('bcrypt');
const passport = require('passport');
exports.user_login = (req, res, next) => {
passport.authenticate('local', (authError, user, info) => {
if (authError) {
console.error(authError);
return next(authError);
}
if (!user) {
return res.send("not user.")
}
return req.login(user, (loginError) => {
if (loginError) {
console.error(loginError);
return next(loginError);
}
return res.send("login successfully")
});
})(req, res, next);
};
model/user.js
const mongoose = require('mongoose');
let UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
require: true
},
createAt: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('User', UserSchema);
const { User } = require('../model/user');
This code return User = undefined
Can you show code in '../model/user'?
Are you export with:
module.exports = {
User: your_user
}
?
If you use:
module.exports = User;
you should call
const User = require('../model/user');
instead of:
const { User } = require('../model/user');
or you can change export in '../model/user':
module.exports = {
User: your_user
}
It should be _id not id in your query
passport/index.js
User.findOne({ _id: id })
.then((user) => done(null, user))
.catch((err) => done(err));
});
In passport/localStrategy file correct import of Model
const User = require('../model/user');

Resources