I've been struggling with Bcrypt on my MERN project, I'm trying to run tests on Postman (registration process), but every time I try it I get this error: Error: Illegal arguments: undefined, string on this line:
if (err) throw err;
This is my server main config file:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const users = require('./routes/api/users');
const profile = require('./routes/api/profile');
const posts = require('./routes/api/posts');
const app = express();
// Body parser Middleware
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
// MongoDB Config
const db = require('./config/keys').mongoURI;
// MongoDB Connection
mongoose
.connect(db)
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
app.get('/', (req, res) => res.send('Hello!'));
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Server Runing on port ${port}`));
// Using Routes
app.use('/api/users', users);
app.use('/api/profile', profile);
app.use('/api/posts', posts);
And this is the users config file where I'm getting the error:
const express = require('express');
const router = express.Router();
const gravatar = require('gravatar');
const bcrypt = require('bcryptjs');
// Load user model:
const User = require('../../models/User');
router.get('/test', (req, res) => res.json({ msg: "Users Works" }));
router.post('/register', (req, res) => {
User.findOne({ email: req.body.email })
.then(user => {
if (user) {
return res.status(400).json({ email: "Email already exists" });
} else {
const avatar = gravatar.url((req.body.email, {
s: '200', // Size
r: 'pg', // Rating
d: 'mm' // Default image
}));
const newUser = new User({
name: req.body.name,
email: req.body.email,
avatar,
password: req.body.password
});
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser.save()
.then(user => res.json(user))
.catch(err => console.log(err));
})
})
}
})
})
module.exports = router;
this is what I see on Postman:
I've been reviewing it and it doesn't seem to have any error, and I really don't get why is telling me "undefined string". If you see any error that I'm not noticing I will truly appreciate your feedback, Thanks in advance!
const newUser = new User({
name: req.body.name,
email: req.body.email,
avatar, <------------------------- avatar:'', or avatar:null,
password: req.body.password
});
Related
Index.Js File:
const cookieSession = require("cookie-session");
const express = require("express");
const app = express();
const helmet = require("helmet");
const morgan = require("morgan");
const dotenv = require("dotenv");
const mongoose = require("mongoose");
const userRoute = require("./routes/user")
const authRoute = require("./routes/auth")
dotenv.config();
//Mongoose Connect
mongoose.connect(process.env.MONGO_URL, {useNewUrlParser: true}, (err) =>
{
console.log("mongdb is connected");
});
//middleware
app.use(express.json());
app.use(helmet());
app.use(morgan("common"));
app.get("/", (req, res) => {
res.send("Welcome to home page");
})
app.use("/api/auth", authRoute);
app.use("/api/user", userRoute);
app.listen(5000,function(err)
{
if(err)
console.log("Server not connected")
console.log("Connnection is established");
})
Auth.Js File
const router = require("express").Router();
const User = require('../model/Users');
//REGISTER
router.get("/register", async (res,req)=> {
const user = await new User({
username: "gauravnegi",
password: "123456",
email: "gauravnegi#gmail.com",
});
await user.save();
res.send("ok");
});
module.exports = router;
Error:
return callback(new error_1.mongoservererror(res.writeerrors [0] ))
Full Error Snippet:
How to resolve above error?
Dear it is not a server side error it's a client side error b/c you have defined somewhere some field {unique:true} in your model! So you should wrap your function inside try-catch block for example
router.get("/register", async (res,req)=> {
try{
const user = await new User({
username: "gauravnegi",
password: "123456",
email: "gauravnegi#gmail.com",
});
await user.save();
res.send("ok");
}catch(error){
//check if it was a duplication error
if(error.code==11000) // show user that it is unique path
and handle other validation error
}
});
I've just included Passport js in my project for auth. But now my POST requests to create a new user hang and return an alert on the client saying "Not authorized" after I close the server. My old code (without Passport) still works so I don't think it's an issue with proxy-ing from client to server
The last console log I see is the first log in the user API, console.log('received request ', req.body)
There are no logged error messages, except when I stop the server I'll get
"Proxy error: Could not proxy request /api/user from localhost:3000 to http://localhost:5000/. [1] See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNRESET).
///app.js (server)
const express = require("express");
const bodyParser = require("body-parser");
const cors = require('cors');
const mongoose = require("mongoose");
const routes = require("./routes"); //Used to end with /api
const path = require("path");
require("dotenv").config();
const passport = require('passport');
const app = express();
const port = process.env.PORT || 5000;
//database
mongoose
.connect(process.env.DB, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log("Database connected successfully"))
.catch((err) => console.log(err));
mongoose.Promise = global.Promise;
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
require('./config/passport');
app.use(cors());
app.use(bodyParser.json());
app.use(passport.initialize());
app.use("/", routes); //Load API - this folder has an index.js file
app.use((err, req, res, next) => {
console.log("$!$", err);
next();
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
///users.js (API for User model)
const passport = require('passport');
const express = require("express");
const router = express.Router();
const User = require("../models/User");
//Old - This works, which makes me think the issue is with Passport js
// router.post("/user", (req, res, next) => {
// try {
// User.create(req.body)
// .then((data) => res.json(data))
// .catch(next);
// } catch {
// res.json({
// error: "Failed to upload new user",
// });
// }
// });
//New
router.post("/user", (req, res, next) => {
console.log('received request ', req.body);
passport.authenticate('register', (err, hashedPassword, info) => {
if (err) {
console.log("Passport err on register ", err);
}
else if (info != undefined) {
console.log("Defined err ", info.message);
res.send(info.message);
} else {
req.login(user, err => {
const newUser = {
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: hashedPassword,
};
User.create(newUser)
.then((data) => res.json(data))
.catch(next);
});
}
});
});
//passport.js (for auth)
const bcrypt = require('bcrypt');
const BCRYPT_SALT_ROUNDS = 12;
const passport = require('passport'),
localStrategy = require('passport-local').Strategy,
User = require('../models/User'),
JWTstrategy = require('passport-jwt').Strategy,
ExtractJWT = require('passport-jwt').ExtractJwt;
const opts = {
jwtFromRequest: ExtractJWT.fromAuthHeaderWithScheme('JWT'),
secretOrKey: 'secret key',
};
passport.use(
'register',
new localStrategy(
{
usernameField: 'email',
passwordField: 'password',
},
(email, password, done) => {
try {
console.log('searching for User');
User.findOne({ email })
.then(user => {
if (user != null) {
console.log('email already taken');
return done(null, false, { message: 'email already in use' });
} else {
console.log('email is available');
bcrypt.hash(password, BCRYPT_SALT_ROUNDS).then(hashedPassword => {
console.log('hashed password created for new user');
return done(null, hashedPassword, null);
});
}
})
} catch(err) {
done(err);
}
}
)
)
passport.authenticate in your code isn't used as a middleware but just like a regular function called inside the request handler. As of passport documentation you should call the returning function when used this way, like this:
passport.authenticate('register', (err, hashedPassword, info) => {
// ...
})(req, res, next); // <- ADD ARGUMENTS AND CALL
I am trying to pass data to a MongoDB collection and it returns Cannot POST /courseweb/course/add
Before passing values through axios I tried postman (a google extension) to send data.
This is my server.js which is implemented with expressjs
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const Bundler = require("parcel-bundler");
const cors = require("cors");
const mongoose = require("mongoose");
const InstructorDB = require('./public/DBModels/InstructorDB');
const router = express.Router();
const bundler = new Bundler("./src/index.html");
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(bundler.middleware());
// app.use(express.static('./src'));
app.use("/courseweb", router);
mongoose.connect("mongodb://127.0.0.1:27017/courseweb", {
useNewUrlParser: true
});
const connection = mongoose.connection;
connection.once("open", () => {
console.log("Connected to MongoDB via 27017");
});
app.listen(3000, err => {
if (err) {
console.error(err);
process.exit(-1);
}
console.log("Application is running on port 3000");
});
app.get("/", function(req, res) {
res.sendFile("./dist/index.html");
});
router.route('/course/add').post((req, res) => {
let instructorDB = new InstructorDB(req.body);
instructorDB.save().then(bookDB => {
res.status(200).send(`${bookDB} Added`);
}).catch((err) => {
res.status(400).send({message: err});
});
});
router.route('/courses').get((req, res) => {
// name of the course database model here
InstructorDB.find().count(function(err, count){
res.status(200).send(count);
});
});
And this is my InstructorDB.js which is a schema model by mongoose
const mongoose= require('mongoose');
const Schema = mongoose.Schema;
let InstructorDB = new Schema({
firstName: String,
lastName: String,
designation: String,
faculty: String,
contactNumber: Number,
email: String,
password: String,
isEnabaled: Boolean,
courses: [{courseID: String}]
});
module.exports = mongoose.model('InstructorDB', InstructorDB, 'InstructorDB');
And this is a screenshot and the response I get when I pass the values through postman. I have set header as content-type and application/json too
Can anyone tell me where I have gone wrong?
Make sure you send the right data via your post request and change the verb to post :
app.post('/course/add', (req, res) => {
if(req.body == null){
return res.status(400).send({message: 'bad request'});
}
let instructorDB = new InstructorDB(req.body);
instructorDB.save((err ,doc ) => {
if(err){
res.status(400).send({message: err});
}
res.status(200).send(`Added`);
});
});
You don't need router if you're going to put it in the same file.
try this syntax instead:
app.post('/coureweb/course/add',((req, res) => {
let instructorDB = new InstructorDB(req.body);
instructorDB.save().then(bookDB => {
res.status(200).send(`${bookDB} Added`);
}).catch((err) => {
res.status(400).send({message: err});
});
}));
then take out
app.use("/courseweb")
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))
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)
}
})
})