So I am trying to build an authentication system using passport in MERN(MongoDB, Express, React, NodeJS).
I set up everything, I connected react with NodeJS,
The problem is when I am trying to log in or register it shows me,
this error "User.findOne is not a function" in the console and I tried to fix it by looking for any
type mistakes or google it but I didn't find anything online.
Did anyone have a similar mistake and fix it or does anyone know how?
Model Code:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ObjectId = Schema.ObjectId;
const UserSchema = new Schema ({
password: String,
email: String,
}, {
collection: 'information'
})
const User = mongoose.model('information', UserSchema);
module.exports - User;
Passport Code:
const Strategy = require('passport-local').Strategy
const mongoose = require('mongoose')
const User = require('../models/user');
const bcrypt = require('bcryptjs')
const salt = bcrypt.genSaltSync(10);
const SignupStrategy = new Strategy ({ passReqToCallback:true, usernameField: 'email' }, function(req, email, password, done){
User.findOne({email: req.body.email}).lean().exec((err, user) => {
if (err) {
return done(err, null);
}
if (user) {
return done("User already exist", null);
}
const encryptedPassword = bcrypt.hashSync(password, salt);
let newUser = new User({
email,
password: encryptedPassword
})
newUser.save((error, inserted) => {
if (error) {
return done(error, null);
}
delete inserted.password;
return done(null, inserted);
})
})
});
module.exports = SignupStrategy;
Node server:
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const passport = require('./passport/');
const PORT = process.env.PORT || 8080;
const mongoose = require('mongoose');
//I have used password in mongo I just did <password> for security reasons.
const mongoString = mongoose.connect('mongodb+srv://herpryth:<password>#nowyourguest-ga5vy.gcp.mongodb.net/users?retryWrites=true&w=majority', {useNewUrlParser: true})
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use('/', indexRouter);
app.use('/authentication', usersRouter);
app.use(passport.initialize());
app.use(passport.session());
app.listen(process.env.PORT || 8080, process.env.IP || '0.0.0.0');
module.exports = app
Route:
const express = require('express');
const app = express.Router();
const passport = require('../passport')
app.post('/signup', (req, res, next) =>{
passport.authenticate('local-signup', function(error, user, info){
if (error) {
return res.status(500).json({
message: error || 'Something happend',
error : error.message || "Server error"
});
}
return res.json(user);
})(req, res, next);
})
app.post('/signin', function(req, res, next){
passport.authenticate('local-signin', function(error, user, info){
if (error) {
return res.status(500).json({
message: error || 'Something happend',
error : error.message || "Server error"
});
}
return res.json(user);
})(req, res, next);
})
module.exports = app;
React server:
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const passport = require('./passport/');
const PORT = process.env.PORT || 8080;
const mongoose = require('mongoose');
const mongoString = mongoose.connect('mongodb+srv://herpryth:XFXGJakc18wBJLIk#nowyourguest-ga5vy.gcp.mongodb.net/users?retryWrites=true&w=majority', {useNewUrlParser: true})
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use('/', indexRouter);
app.use('/authentication', usersRouter);
app.use(passport.initialize());
app.use(passport.session());
app.listen(process.env.PORT || 8080, process.env.IP || '0.0.0.0');
module.exports = app
Does anyone know how to fix this problem?
There is just a simple mistake in your code
replace with
module.exports = User
to
module.exports - User
Related
My node/Express app is displaying strange behavior.
I have the following code:
// app.js
const express = require('express');
const router = require('express').Router();
const bodyParser = require('body-parser');
const dotenv = require('dotenv');
const path = require('path');
const cors = require('cors');
dotenv.config({ path: path.resolve(__dirname, '.env.local') });
dotenv.config();
const port = process.env.PORT || 5000;
const passport = require('passport');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const PostgreSqlStore = require('connect-pg-simple')(session);
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
app.use(cors());
app.options('*', cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser(process.env.SECRET_KEY));
app.use(session({
store: new PostgreSqlStore({
conString: `postgres://${process.env.DB_USER}:${process.env.DB_PASS}#${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`,
}),
secret: process.env.SECRET_KEY,
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
require('./auth/passport.js')(passport);
const routes = require('./api/routes')(router, passport);
app.use('/', routes);
app.listen(port, () => {
console.log(`App running on port ${port}.`)
})
module.exports = app;
// /api/routes.js
const api = require('./api');
module.exports = function(router, passport) {
router.get('/users', (req, res, next) => {
api.getUsers(req, res, next);
})
return router;
}
// /api/api.js
const Promise = require('bluebird');
const initOptions = {
promiseLib: Promise,
}
const pgp = require('pg-promise')(initOptions);
const db = pgp({
user: process.env.DB_USER,
host: process.env.DB_HOST,
database: process.env.DB_NAME,
password: process.env.DB_PASS,
port: process.env.DB_PORT,
});
const getUsers = (req, res, next) => {
db.task(t => {
return t.any('SELECT * FROM users ORDER BY uuid ASC')
.then((result) => {
res.json(result);
})
.catch(error => console.error(error));
})
}
module.exports = {
db,
getUsers,
}
If I run the server and cURL localhost:5000/users the app just sits there and doesn't return any data. However, if I Ctrl + C to stop the server connection, it gives me the following:
curl: (18) transfer closed with 1 bytes remaining to read
The weird thing is that this is followed by the data that's missing! I.e. it's not getting sent until the server is shut down.
Postman call never gives a response.
Console.logging result outputs the expected/missing data in the console.
The data's there, but res.send and res.json are doing nothing. I'm sure it has to do with Promises, but I'm not sure what I'm missing. I've also tried to use Pools and Clients for the database queries, instead of pg-promise, but to the same result.
I figured out the issue. I needed to use Pool correctly and tie it into the session.
// app.js
const express = require('express');
const router = require('express').Router();
const bodyParser = require('body-parser');
const dotenv = require('dotenv');
const path = require('path');
dotenv.config({ path: path.resolve(__dirname, '.env.local') });
dotenv.config();
const pool = require('./api/api').pool;
const cors = require('cors');
const port = process.env.PORT || 5000;
const passport = require('passport');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const PostgreSqlStore = require('connect-pg-simple')(session);
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
app.options('*', cors());
app.use('*', bodyParser.json());
app.use('*', bodyParser.urlencoded({ extended: true }));
app.use(cookieParser(process.env.SECRET_KEY));
app.use(session({
store: new PostgreSqlStore({
pool,
}),
secret: process.env.SECRET_KEY,
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
require('./auth/passport.js')(passport);
const routes = require('./api/routes')(router, passport);
app.use('/', routes);
app.listen(port, () => {
console.log(`App running on port ${port}.`)
})
module.exports = app;
// api/routes.js
const api = require('./api');
module.exports = function(router, passport) {
router.get('/users', (req, res, next) => {
api.getUsers(req, res, next);
})
return router;
}
// api/api.js
const Pool = require('pg').Pool
const pool = new Pool({
user: process.env.DB_USER,
host: process.env.DB_HOST,
database: process.env.DB_NAME,
password: process.env.DB_PASS,
port: process.env.DB_PORT,
});
const getUsers = (req, res, next) => {
pool.connect((err, client, done) => {
if (err) {
throw err
}
return client.query('SELECT * FROM users ORDER BY uuid ASC', (err, result) => {
if (err) {
console.error(error);
} else if (result.rowCount > 0) {
res.send(result.rows);
}
else {
res.sendStatus(500);
}
})
})
}
module.exports = {
pool,
getUsers,
}
Getting a 404 error on my POST route, here is what I have done in my auth.js (routes) file:
const express = require('express');
const router = express.Router();
const connection = require('../../helpers/db.js');
const bodyParser = require("body-parser");
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({
extended: true
}));
//create a new user
router.post('/signup', function (req, res) {
const insert = `INSERT INTO users ( email, password, name, lastname) values ('${req.body.email}', '${req.body.password}','${req.body.name}', '${req.body.lastname}' )`
connection.query(insert, function (err, result) {
if(err) {
console.log('mysql error', error);
res.status(500);
res.send(error);
} else {
console.log('a new user was added!');
res.send('Congrats, new user!');
}
})
});
module.exports = router;
Here is my app.js file:
const http = require("http");
const path = require("path");
const express = require("express");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const app = express();
const authRouter = require("./routes/auth/auth");
// Configuring the app
app.use(morgan("dev"));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(__dirname + "/public"));
app.use("/signup", authRouter);
//starting node server
const server = app.listen(process.env.PORT || 3001, function(err) {
if(err) throw err;
console.log("Listening on port " + server.address().port);
});
If I change my route into a GET, it works fine, but as soon as I do a POST route it would keep telling me on postman there is a 404 error, been trying many things but im now stuck! Im a beginner here :)
I think you added a prefix to your route so the route is /signup/signup
Try to change this
app.use("/signup", authRouter);
To this
app.use(authRouter);
this is my app.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const cors = require('cors');
const passport = require('passport');
const app = express();
app.use(cors());
//Mongodb connection
mongoose.connect("mongodb://localhost/expressWithAngular")
.then(() => {
console.log("mongodb connected");
})
//bodyparser middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//load routes
const users = require("./routes/users");
//include passport
require("./config/passport")(passport);
// use routes
app.use('/user' , users);
app.get('' ,(req,res) => {
res.send('home');
})
const port = 5000;
app.listen(port , () => {
console.log(`server is running in port ${port}`);
})
this is my user routes routes/user.js
const express = require('express');
const mongoose = require('mongoose');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
//user model init
require('./../models/User');
const User = mongoose.model('users');
router.post('/login' , (req,res,next)=>{
console.log("bodyparser" ,req.body);
passport.authenticate('local',{
session: false
},function(req,res,next){
console.log(res);
})
})
module.exports = router;
this is my config/passport.js
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const User = mongoose.model('users');
module.exports = function(passport){
passport.use(new LocalStrategy(
{
usernameField : 'email'
},
function(email,password,done){
console.log(email);
}
))
}
- i was trying to connect my mean stack app with passport
authentication, i am able to send details to backend but i couldn't
pass the value to local strategy
- I don't know where i am missing, when i consoled the local strategy is
not called, please correct me where i am missing
I believe that you have problem in your router configuration. passport.authenticate is generating middleware for you, but in your case you have wrapped it in function so you could log input parameters and you haven't returned generated middleware to router:
router.post('/login' , (req,res,next)=>{
console.log("bodyparser" ,req.body);
passport.authenticate('local',{
session: false
},function(req,res,next){
console.log(res);
})
})
I would advise you to modify your code to work like in example in official documentation:
router.post('/login' , passport.authenticate('local',{
session: false
});
)
If you really need to log req.body just add a middleware before authentication like this:
router.post('/login' , (req, res, next) {
console.log("bodyparser" ,req.body);
next();
},
passport.authenticate('local', {session: false});
)
When I did res.json (newschema) on post action, the properties are not displayed any more on Postman and also in Mongodb.
This is formations.routes
const express = require('express');
const router = express.Router();
const Formation = require('../models/formations');
const mongoose = require('mongoose');
const config = require('../config/database');
router.get('/', function(req, res){
//Formation.getFormations(function(err, formations){
// if(err)throw err;
// res.json(formations);
//});
Formation.find({})
.exec(function(err, Formations){
if(err){
console.log('error');
}else{
res.json(Formations);
}
})
});
router.post('/', function(req, res){
console.log('post a formations');
var newFormation = new Formation();
newFormation.title = req.body.title;
newFormation.url = req.body.url;
newFormation.description = req.body.description;
newFormation.save(function(err, newFormation){
if(err){
console.log('error insertion');
} else {
res.json(newFormation);
//res.json({success: true, msg:'user registred'});
}
});
});
This is formation.models
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const config = require('../config/database');
const FormationSchema = mongoose.Schema ({
title: String,
url: String,
description: String
});
module.exports = mongoose.model('Formation', FormationSchema, 'Formations');
This is my app.js ( endpoint)
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const cors = require('cors');
const passport = require('passport');
const mongoose = require('mongoose');
const config = require('./config/database');
const User = require('./models/user');
const Formation = require('./models/formations');
mongoose.connect(config.database , { useNewUrlParser: true });
mongoose.connection.on('connected', () => {
console.log('connected to database... ' + config.database);
});
mongoose.connection.on('error', (err) => {
console.log('database error'+err);
});
/*mongoose.connect('mongodb://localhost:27017/hello', { useNewUrlParser: true });
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log('we are connected!');
});*/
const app = express();
const users = require('./routes/users');
const formations = require('./routes/formations');
//port number
const port = 3001;
//cors middleware
app.use(cors({
origin: 'http://localhost:4200'
}));
//passwport middelware
app.use(passport.initialize());
app.use(passport.session());
require('./config/passport')(passport); //pour implémenter fichier passport.js
//set static folder
app.use(express.static(path.join(__dirname + '/public')));
//BodyParser middleware
app.use(express.json());
app.use(bodyParser.json());
app.use('/users', users);//hedhiya ki nekteb /users barka f url yemchili direct lel const users = require('./routes/users'); fichier hedhka
app.use('/formations', formations);
//c un route
//just meloul 7atineha bch ntastiw beha
//index route
app.get('/', function(req, res){
res.send('invalid endpoint');
});
//start Server
app.use(bodyParser.urlencoded({extended:true}));
app.listen(port, () => {
console.log('Server started on port' +port);
});
And this is how I make a post action in Postman
The save method only has an error parameter in the callback. You are adding a newFormations parameter which will always be undefined and in the scope of the method you are returning undefined in the res.json call. To fix it remove the newFormation parameter as below:
newFormation.save(function(err){
if(err){
console.log('error insertion');
} else {
res.json(newFormation);
//res.json({success: true, msg:'user registred'});
}
});
Like i said in title. req.body don't work. I saw some examples and that use req.body(body-parser) well. But in my code, req.body is keep undefined. Also i found same problems and they said "app.use(bodyParser.json())" will work. But for me, no. So i ask how can i solve this error. Plz, help me.
This code is simple, Express and Vue login, signin test project. I think problem is in server file.
Server
var express = require("express");
var bodyParser = require("body-parser");
var path = require("path");
const mongoose = require("mongoose");
var index = require("./routes/index.js");
var login = require("./routes/login.js");
var signin = require("./routes/signin.js");
var app = express();
var http = require("http").Server(app);
mongoose.connect("mongodb://localhost:27017/test");
app.use('/', index);
app.use('/api/login', login);
app.use('/api/signin', signin);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.set("port", process.env.PORT || 3000);
app.use(express.static(path.join(__dirname, 'public')));
http.listen(app.get("port"), function() {
console.log("server start in " + app.get("port"));
})
Router
const express = require("express");
const router = express.Router();
const User = require("../models/user.js");
router.post("/", function(req, res, next) {
const id = req.body.id;
const password = req.body.password;
let info = {
error: "false",
words: "",
id: "",
password: ""
}
User.findOne({ id: id }, function(err, user) {
if(err) {
info.error = "true";
info.words = "Unknown Error Come Out.";
return res.send(info);
}
if(!user) {
info.error = "true";
info.words = "Please Check Your ID or Password";
return res.send(info);
}
info.id = id;
info.password = password;
console.log(info);
return res.send(info);
})
});
module.exports = router;
This body can not be resolved because of your middleware declaration order. You can check from the following blog about middleware execution sequence. Basically it equals to middleware declaration order.
https://derickbailey.com/2016/05/09/in-what-order-does-my-express-js-middleware-execute/
Declare bodyParser middleware before router middleware can solve your problem
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/api/login', login);