Node.js Mongodb Intergration Issues; .save() - javascript

This is an example site that I have created with a basic Node.js server. I am able to successfully post, create a user given the schema, and "save" to the database; however, saving does not return the user object and cannot be found in my actual database. The connection is also returned as successful.
main.js
const session = require('express-session');
const pug = require('pug');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const User = require('./schema.js');
const app = express();
var path = require('path');
const MongoClient = require('mongodb').MongoClient;
const client = new MongoClient('mongodb://localhost:27017');
var db;
client.connect((err, client) => {
if (err) {
console.log(err);
}
else if (!err) {
db = client.db('node');
console.log('Connected to Mongodb');
client.close()
}
});
app.engine('pug', require('pug').__express)
app.set('view engine', 'pug');
app.use(bodyParser.urlencoded({ extended : true }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'styles')));
app.use(session({secret: 'testing',saveUninitialized: true,resave: true}));
//root directory get response
app.get('/', (req, res) => {
res.render('homepage', {
title : 'Homepage',
req : req
});
});
//register directory get response
app.get('/register', (req, res) => {
res.render('register', {
title : 'Register',
req: req
});
});
//profile directory get response
app.get('/profile', (req, res) => {
res.render('profile', {
title: 'Profile',
email: req.session.email,
username: req.session.username,
req: req
});
});
//login directory get response
app.get('/login', (req, res) => {
res.render('login', {
title: 'Login',
req: req
})
})
//register directory post request
app.post('/register', (req, res) => {
console.log(req.body);
if(req.body.username && req.body.email && req.body.password){
var user = User({
email : req.body.email,
username : req.body.username,
password : req.body.password
});
console.log(user);
user.save((err) => {
user.markModified('password')
console.log("Trying to save")
console.log(user)
if(err){
console.log(err);
} else {
var sess = req.session;
sess.email = req.body.email;
console.log("Saved")
res.redirect('/profile')
}
});
}
});
//login directory post request
app.post('/login', (req, res) => {
console.log(req.body);
if(req.body.username && req.body.password){
var sess = req.session;
sess.username = req.body.username;
res.redirect('/profile')
}
})
const server = app.listen(8000, () => {
console.log(`Express running → PORT ${server.address().port}`);
});
schema.js
const bcrypt = require('bcrypt');
var UserSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
trim: true
},
username: {
type: String,
unique: true,
required: true,
trim: true
},
password: {
type: String,
unique: false,
required: true,
trim: true
}
});
UserSchema.pre('save', function(req, err, next) {
var user = this;
bcrypt.genSalt(10, (err, salt) => {
if(err){
return next(err);
}
bcrypt.hash(user.password, salt, (err, hash) => {
if(err){
return next(err);
}
user.password = hash;
console.log(hash);
next()
});
});
});
var User = mongoose.model('User', UserSchema);
module.exports = User;

You are using mongoose to create models and make db querys but not connecting to mongoose. Instead you are connecting to MongoDb native driver.
Replace this
const MongoClient = require('mongodb').MongoClient;
const client = new MongoClient('mongodb://localhost:27017');
var db;
client.connect((err, client) => {
if (err) {
console.log(err);
}
else if (!err) {
db = client.db('node');
console.log('Connected to Mongodb');
client.close()
}
});
with
mongoose.connect(connectionString, {useNewUrlParser: true});
mongoose.connection.on("open", function(ref) {
console.log("Connected to mongo server.");
});
mongoose.connection.on("error", function(err) {
console.log("Could not connect to mongo server!");
console.log(err);
});

Try this var user = new User({ ... }); instead of this var user = User({ ... });. Notice the new keyword.

Related

Trying to log in user using mongodb and nodejs

im trying to log a user in but keep getting the error user is not defined ive tried using both upper and lowercase "user/User" but its still saying undefined.
var mongoose = require("mongoose")
var Schema = mongoose.Schema
//var bcrypt = require("bcrypt-nodejs")
var bcrypt = require("bcryptjs")
mongoose.set('useCreateIndex', true,
);
var userSchema = new Schema({
fname: { type: String, required: true },
lname: { type: String, required: true },
email: { type: String, set: toLower, required: true },
address: { type: String, required: true },
phonenumber: { type: String, required: true },
city: { type: String, required: true },
state: { type: String, required: true },
country: { type: String, required: true },
zipcode: { type: Number, required: true },
cpassword: { type: String, required: true }
})
var db = mongoose.createConnection('mongodb://localhost/main', {
useNewUrlParser: true,
useUnifiedTopology: true
});
userSchema.statics.authenticate =
function (email, password, callback) {
console.log('im here')
user.findOne({ email: email })
.exec(function (err, user) {
if (err) {
return callback(err)
} else if (!user) {
var err = new Error('User not found!');
err.status = 401;
return callback(err);
} else {
bcrypt.compare(password, user.cpassword, function (err, result) {
if (result === true) {
return callback(null, user);
} else {
return callback('Wrong password!');
}
})
}
});
}
//userSchema.methods.authenticate = function (password) {
userSchema.methods.validPassword = function (password) {
return bcrypt.compareSync(password, this.cpassword)
}
/*
//}
userSchema.methods.encryptPassword = function (cpassword) {
return bcrypt.hashSync(cpassword, bcrypt.genSaltSync(5), null)
}
/*
userSchema.methods.validPassword = function (cpassword) {
return bcrypt.compareSync(cpassword, this.cpassword)
}
*/
function toLower(str) {
return str.toLowerCase();
}
//userSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", userSchema, "users")
Above is the model-users.js file
Below is my server.js file
var express = require('express');
const app = express();
var bodyParser = require("body-parser");
var router = express.Router();
var path = require('path');
var passport = require('passport');
const flash = require('connect-flash');
var LocalStrategy = require("passport-local").Strategy;
var user = require('./models/user-model.js');
var config = require('./passport-config')
const methodOverride = require('method-override')
var morgan = require('morgan')
const get = require('./insert.js');
//const register = require('./register.js');
const mongoose = require('mongoose')
const session = require('express-session');
const { check, validationResult }
= require('express-validator');
const MongoStore = require('connect-mongo')(session);
var bcrypt = require("bcryptjs");
const { triggerAsyncId } = require('async_hooks');
mongoose.connect('mongodb://localhost/main', {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true
});
app.use(session({
store: new MongoStore({ mongooseConnection: mongoose.connection, collection: 'sessions', }
),
secret: 'keyboard cat',
resave: true,
saveUninitialized: true,
unset: 'destroy',
cookie: {
secure: false,
}
}));
var db = mongoose.createConnection('mongodb://localhost/main', {
useNewUrlParser: true,
useUnifiedTopology: true
});
app.set('views', __dirname + '/views');
app.set('view engine', 'pug');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true,
}));
app.use(morgan('dev'))
app.use(flash())
// ROUTES
app.get('/about', function (req, res) {
res.render('about,{ title: "About Us" }')
})
app.get('/contact', function (req, res) {
res.render('contact', { title: "Contact Us" });
});
app.get('/index', function (req, res) {
res.render('index', { title: "Home" });
});
app.get('/bookingform', function (req, res) {
res.render('bookingform', { title: "Book Your Tour" });
});
app.get('/login', function (req, res) {
res.render('login', { title: "Login" });
});
app.get('/tours', function (req, res) {
res.render('tours', { title: "Tours" });
});
app.get('/', (req, res) => {
app.use(express.static(path.join(__dirname + '/public')));
res.render('index');
})
app.get('/signup', (req, res) => {
//app.use(express.static(path.join(__dirname + '/public')));
res.render('signup');
})
app.get('/checkout', (req, res) => {
get(req, res);
res.render('checkout')
})
//
app.post('/insert', (req, res) => {
get(req, res);
console.log(req.body)
});
app.post("/login",
function (req, res, next) {
if (req.body.email && req.body.password) {
console.log(req.body)
db.collection("users")
user.authenticate(req.body.email, req.body.password,
function (error, user) {
if (error || !user) {
error.status = 401;
return next(error);
}
else {
//res.send(user);
console.log("Sign in Successfull ")
res.redirect('about');
}
}
);
}
else {
var err = new Error('Something went wrong!');
err.status = 400;
res.render('login', { notif: err })
return next(err);
}
console.log('failed')
},
)
function checkPassword(password) {
return bcrypt.compareSync(password, user.cpassword)
}
function findUserByEmail(email) {
if (email) {
return new Promise((resolve, reject) => {
user.findOne({ email: email })
.exec((err, doc) => {
if (err) return reject(err)
if (doc) return reject(new Error('This email already exists. Please enter another email.'))
else return resolve(email)
})
})
}
}
//Handling user logout
app.get("/logout", function (req, res) {
req.logout();
res.redirect("/");
});
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) return next();
res.redirect("/login");
}
function checkAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next()
}
res.redirect('/login')
}
function unWindMessages(em) {
var m = [];
for (var i in em) {
m.push(em[i].msg);
}
return m;
}
function checkNotAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return res.redirect('/')
}
next()
}
app.listen(27017, function () {
console.log('listening on 27017')
})
module.exports = app;
So far i have tried specifying the database collection to use in both files , it didnt work still getting user not defined.
I fixed it by making a User variable that stored the model.
var User = mongoose.model("User", userSchema, "users")
module.exports = User

Express APP how to redirect user to /:id path from server side

I'm learning Node.js and I'm finding some troubles with redirecting the user to an :id path. I would like to print there his username.
So to make an overview it is a landing page with a form where I ask for an Alias and an email. When user clicks submit I'd like to move him to /:id path to print its' username.
My code is the following:
var express = require("express"),
app = express(),
request = require("request"),
mongoose = require("mongoose"),
bodyParser = require("body-parser");
app.set("view engine", "ejs")
app.use(express.static("public"));
app.use(bodyParser.urlencoded({extended: true}));
mongoose.connect("mongodb://localhost/Scape_Room", {useNewUrlParser: true, useUnifiedTopology: true});
var userSchema = new mongoose.Schema({
email: String,
alias: String,
});
var user = mongoose.model ("user",userSchema);
app.get("/", function(req, res){
res.render("index")
})
app.post("/newuser", function(req,res){
var name = req.body.name;
var email = req.body.email;
var newUser = {name:name, email:email}
user.create(newUser, function(err,newlyUser){
if(err){
console.log(err)
} else {
res.redirect("/start/:id")
}
})
})
app.get("/start/:id", function(req,res){
user.findById(req.params.id, function(err, foundUser){
if(err){
console.log(err)
} else{
res.render("startPoint", {user:foundUser})
}
})
})
app.listen(3000, function(err){
console.log("Server listening")
})
error is the following: { CastError: Cast to ObjectId failed for value ":id" at path "_id" for model "user"
I've tried:
- to change the path to :_id
- added start/ into the route
When you are using the redirect() method, you must pass a real route url not an id.
const express = require("express")
const request = require("request");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const app = express();
app.set("view engine", "ejs")
app.use(express.static("public"));
mongoose.connect("mongodb://localhost/Scape_Room", { useNewUrlParser: true, useUnifiedTopology: true });
const userSchema = new mongoose.Schema({
email: String,
alias: String,
});
const user = mongoose.model("user", userSchema);
app.get("/", function (req, res) {
res.render("index");
});
app.post("/newuser", function (req, res) {
const { name, email } = req.body;
if (!name || !email) {
return res.end();
}
const newUser = { name: name, email: email }
user.create(newUser, function (err, newlyUser) {
if (err) {
console.log(err);
return res.end();
}
if (!newlyUser) {
console.log("Couldn't save user!");
return res.end();
}
if (!newlyUser.id) {
console.log("No user id found");
return res.end();
}
res.redirect(`/start/${newlyUser.id}`);
});
});
app.get("/start/:id", function (req, res) {
user.findById(req.params.id, function (err, user) {
if (err) {
console.log(err);
} else {
res.render("startPoint", { user });
}
})
})
app.listen(3000, function (err) {
console.log("Server listening")
});
Use something like below
app.post("/newuser", function(req,res){
var name = req.body.name;
var email = req.body.email;
var newUser = {name:name, email:email}
user.create(newUser, function(err,newlyUser){
if(err){
console.log(err)
} else {
res.redirect(`/start/${newlyUser._id}`)
}
})
})

NodeJS: Why is email undefined during user registration?

I am developing an API using NodeJS with the functionality of user registration and login. When a user register, I get
"Error: WHERE parameter "email" has invalid "undefined" value" this
error."
I have checked similar question and answer here and tried every one of them, but none has worked for me.
app.js file
```
//use path module
const path = require('path');
//use express module
const express = require('express');
//use ejs view engine
const ejs = require('ejs');
//use bodyParser middleware
const bodyParser = require('body-parser');
//use mysql database
const mysql = require('mysql');
const app = express();
//Setting port number
const port = process.env.PORT || 619;
const mysqlConnection = mysql.createConnection({
host: 'localhost',
user:'root',
password: '',
database: 'home_automation_db'
});
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(function(req, res, next) {
res.locals.stuff = {
url : req.originalUrl
}
next();
});
//connecting to database
mysqlConnection.connect((err) =>{
if(!err)
console.log('DB connection successful');
else
console.log('connection failed \n Error: '+JSON.stringify(err, undefined, 2));
});
var Users = require('./controllers/lightController');
app.use('/users', Users);
//server listening
app.listen(port, () => {
console.log('Server is running at port '+port);
});
lightcontroller.js
```var bodyParser= require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
var generator = require('generate-password');
var nodemailer = require('nodemailer');
const bcrypt = require('bcrypt');
const cors= require('cors')
const jwt = require('jsonwebtoken');
const express =require('express')
const users = express.Router();
const User = require('../models/User');
users.use(cors());
process.env.SECRET_KEY = 'secret';
```
```
// Login controller
users.post('/register', function (req, res) {
const userData = {
user_name: req.body.username,
email: req.body.email,
password: req.body.password,
location: req.body.location,
house_number: req.body.house_number
}
User.findOne({
where: {
email: req.body.email
}
}).then(user => {
if (!user) {
bcrypt.hash(req.body.password, 10, (err, hash) => {
userData.password = hash
User.create(userData).then(user => {
res.json({ status: user.email + "registered" })
}).catch(err => {
res.send('error: ' + err)
})
})
} else {
res.json({ error: "user already exist." })
}
}).catch(err => {
res.send('error: '+err)
})
});
```
User model
const Sequelize = require('sequelize')
const db = require("../database/db")
module.exports = db.sequelize.define(
'user_tb',
{
user_id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
user_name: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
location: {
type: Sequelize.STRING
},
house_number: {
type: Sequelize.STRING
}
},
{
timestamps: false,
freezeTableName: true
}
)
As #messerbill said the most probable cause is the sending of data as undefined
Try adding config after post data to your post request on the client side so it sets proper content-type:
axios.post('http://localhost:9000/api/login', {
email: this.state.email,
password: this.state.password,
}, {
'content-type': 'x-www-form-urlencoded'
}).then(res => {
console.log(res);
if(res.status) {
console.log('User is logged in');
}
}).catch(err => console.log(err))

ExpressJS with html5mode while fetching API not working

I am trying to remove the # sign on the URL using html5mode by stating the location provider html5mode to true
$locationProvider.html5Mode(true);
I also did configured my server.js file to serve my static files and my index.html as below
var express = require('express'),
app = express(),
mongoose = require('mongoose'),
bodyParser = require('body-parser'),
port = process.env.PORT || 8080;
app.use('/app', express.static(__dirname + '/public/app'));
app.use('/assets', express.static(__dirname + '/public/assets'));
app.use('/libs', express.static(__dirname + '/public/libs'));
app.all('/*', function(req, res, next) {
res.sendFile('/public/index.html', { root: __dirname });
});
app.use(bodyParser.json());
require('./app/routes.js')(app);
app.listen('8080');
console.log('The magic happens on port 8080');
At this point, everything works fine from localhost:8080 to other navigation such as localhost:8080/login even when I refreshed the page, it is still working fine.
It it not working during any API fetch statement is being called. Below is my routes.js
route.js
var mongoose = require('mongoose'),
db = mongoose.createConnection('mongodb://127.0.0.1/database'),
Role = require('./models/role.js')(db);
User = require('./models/user.js')(db);
module.exports = function(app) {
app.route('/api/user')
.get(function(req, res, next) {
User.find(function(err, user){
if(err)
res.json(err);
res.json(user);
});
})
.post(function(req, res, next) {
var error_return = [{response:'User Existed'},{response:'Invalid Username or Password'},{response:'Server Error'}];
if(req.body.type === "local"){
var newUser = new User();
newUser.first_name = req.body.first_name;
newUser.last_name = req.body.last_name;
newUser.email = req.body.email;
newUser.password = newUser.generateHash(req.body.password);
newUser.type = req.body.type;
newUser.role = req.body.role;
User.findOne({email: req.body.email}, function (err, user) {
if (err) {
res.json(error_return[2]);
return;
}
if (!user){
newUser.save(function(error, result){
if(error)
res.json(error_return[2]);
res.json({response:result});
});
return;
}
res.json(error_return[0]);
});
}else if(req.body.type === "login"){
User.findOne({email: req.body.email}, function (err, user) {
if (err) {
res.json(error_return[2]);
return;
}
if (!user){
res.json(error_return[1]);
return;
}
if (!user.validPassword(req.body.password)){
res.json(error_return[1]);
return;
}
res.json({response:user});
});
}
});
};
Previously before enabling html5mode, my files in require('./app/routes.js')(app); is running smoothly, after enabling, it is not even being called. Have I missing something in my code?
All your requests are going to public/index.html right now.
Modify your code to allow /api/ requests to go to the routes
app.use('/api', bodyParser.json(), require('./app/routes.js'));
app.use('/app', express.static(__dirname + '/public/app'));
app.use('/assets', express.static(__dirname + '/public/assets'));
app.use('/libs', express.static(__dirname + '/public/libs'));
app.all('/*', function(req, res, next) {
res.sendFile('/public/index.html', { root: __dirname });
});
app.listen('8080');
console.log('The magic happens on port 8080');
routes.js
var mongoose = require('mongoose'),
db = mongoose.createConnection('mongodb://127.0.0.1/database'),
Role = require('./models/role.js')(db),
User = require('./models/user.js')(db),
router = require('express').Router();
module.exports = router;
router.route('/user')
.get(function (req, res, next) {
User.find(function (err, user) {
if (err) res.json(err);
res.json(user);
});
})
.post(function (req, res, next) {
var error_return = [{
response: 'User Existed'
}, {
response: 'Invalid Username or Password'
}, {
response: 'Server Error'
}];
if (req.body.type === "local") {
var newUser = new User();
newUser.first_name = req.body.first_name;
newUser.last_name = req.body.last_name;
newUser.email = req.body.email;
newUser.password = newUser.generateHash(req.body.password);
newUser.type = req.body.type;
newUser.role = req.body.role;
User.findOne({
email: req.body.email
}, function (err, user) {
if (err) {
res.json(error_return[2]);
return;
}
if (!user) {
newUser.save(function (error, result) {
if (error) res.json(error_return[2]);
res.json({
response: result
});
});
return;
}
res.json(error_return[0]);
});
} else if (req.body.type === "login") {
User.findOne({
email: req.body.email
}, function (err, user) {
if (err) {
res.json(error_return[2]);
return;
}
if (!user) {
res.json(error_return[1]);
return;
}
if (!user.validPassword(req.body.password)) {
res.json(error_return[1]);
return;
}
res.json({
response: user
});
});
}
});

Mongoose: TypeError: 'mongooseSchemahere' is not a function

I have the following mongoose Schema setup in models/user.js:
const mongoose = require('mongoose');
const userSchema = mongoose.Schema({
loginId: String,
firstname: String,
lastname: String,
eMail: String,
password: String,
active: Boolean
});
module.exports = userSchema;
In my main app.js I have the following code:
const mongoose = require('mongoose');
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, {
useUnifiedTopology: true,
useNewUrlParser: true,
},function(err, db) {
if (err) throw err;
var dbo = db.db("db");
dbo.collection("db").find({}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
db.close();
});
});
let userSchema = require('./models/user.js');
// Get single user
app.get('/user/:id', function (req, res) {
userSchema.findById(req.params.id, (error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
})
I get the error which is in the title (just replace mongooseSchemahere with userSchema). What did I do wrong? I tried putting the userSchema declaration in different places, it did not help..
You need to use mongoose.connect to work with mongoose models.
Make these changes:
1-) Create the user model like this and export:
const mongoose = require("mongoose");
const userSchema = new mongoose.Schema({
loginId: String,
firstname: String,
lastname: String,
eMail: String,
password: String,
active: Boolean
});
module.exports = mongoose.model("User", userSchema);
2-) Change your App.js to connect your db with mongoose.connect:
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const User = require("./models/user");
const url = "mongodb://localhost:27017/mydb";
const port = process.env.PORT || 3000;
app.use(express.json());
mongoose
.connect(url, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
app.listen(port, () => {
console.log(`App running on port ${port}...`);
});
})
.catch(error => console.log(error));
Now you can create a user like this:
app.post("/user", function(req, res, next) {
console.log("Req body:", req.body);
User.create(req.body)
.then(result => {
console.log({ result });
res.send(result);
})
.catch(err => {
console.log(err);
res.status(500).send("something went wrong");
});
});
To retrieve the user by _id:
app.get("/user/:id", function(req, res, next) {
User.findById(req.params.id, (error, data) => {
if (error) {
return next(error);
} else {
res.json(data);
}
});
});
To retrieve a user by firstname: (if you want to find all users by firstname change findOne to find.):
app.get("/user/firstname/:firstname", function(req, res, next) {
console.log(req.params.firstname);
User.findOne({ firstname: req.params.firstname }, (error, data) => {
if (error) {
return next(error);
} else {
res.json(data);
}
});
});
You need to export the model and not the schema.
const mongoose = require('mongoose');
const userSchema = mongoose.Schema({
loginId: String,
firstname: String,
lastname: String,
eMail: String,
password: String,
active: Boolean
});
module.exports = mongoose.model('user', userSchema);
Now you can do things like:
let User = require('./models/user.js');
// Get single user
app.get('/user/:id', function (req, res) {
User.findById(req.params.id, (error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
})

Categories