I'm really new to NodeJs and MongoDB or web development in general. I'm following a tutorial on how to make a registration system that was posted about 2 years ago. With these codes below, he was able to send a post request test using postman and his data was saved into MongoDB, however, when I try to send a post request on postman, it keeps loading at "sending request" and data was never saved to mongoDB...I'm not sure if nodejs has changed syntax or if i'm doing something wrong... please help!!
this is the code for user.controller.js
const mongoose = require('mongoose');
const User = mongoose.model('User');
module.exports.register = (req, res, next) => {
var user = new User();
user.fullName = req.body.fullName;
user.email = req.body.email;
user.password = req.body.password;
user.save((err, doc) => {
if (!err)
res.send(doc);
else {
if (err.code == 11000)
res.status(422).send(['Duplicate email adrress found.']);
else
return next(err);
}
});
this is the code for user.model.js:
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
var userSchema = new mongoose.Schema({
fullName: {
type: String
},
email: {
type: String
},
password: {
type: String
},
saltSecret: String
});
// Events
userSchema.pre('save', function (next) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(this.password, salt, (err, hash) => {
this.password = hash;
this.saltSecret = salt;
next();
});
});
});
mongoose.model('User', userSchema);
this is the code for server(app.js)
const MongoClient = require('mongodb').MongoClient;
const uri = process.env.MONGODB_URI;
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
client.connect(err => {
const collection = client.db("test").collection("devices");
// perform actions on the collection object
console.log(`MONGODB CONNECTION SUCCEEDED`);
client.close();
});
require('./user.model');
In controller you have mongoose to write data to mongo but in your server file you are connecting to mongodb using native mongo driver. Hence, it won't work. Either both places you need to have mongodb native driver or mongoose.
Use below code where I have modified the server start file to use mongoose.
const mongoose = require('mongoose'),
const m_url = 'mongodb://127.0.0.1:27017/',
db_name = 'test', // use your db name
m_options = {
'auto_reconnect': true,
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
}
mongoose.connect(m_url + db_name, m_options, function (err) {
if (err) {
console.log('Mongo Error ' + err);
} else {
status.mongo = 'Running'
console.log('MongoDB Connection Established');
}
});
// import/require user controller.
Related
App.js file->Connection is established successfully, but in find() callback,data is empty[]
const express = require('express');
const mongoose = require('mongoose');
const Users = require('./users');
const app = express();
mongoose.connect("mongodb+srv://sanjeev:**pass**#cluster0.ckywrym.mongodb.net?retryWrites=true&w=majority/sanjeevDb",
{
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(() => console.log("connection established successfully"));
Within find callback I am getting empty array in data
Users.find({}, (error, data) => {
if (error)
console.log("Error: ", error);
console.log(data)
});
users.js - defining the schema as same on mongoDb Atlas
const mongoose = require('mongoose');
let userSchema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: String,
email: String,
country: String
});
module.exports= mongoose.model('userCollect', userSchema);
enter image description here
you are logging data even when there is error. do this
Users.find({}, (err, data) => {
if (err){
console.log(err);
} else {
console.log(data);
})
or
//with async (recommended)
try {
const users = await Users.find({});
console.log(users);
} catch (err) {
console.log(err);
}
The problem start when I use the bcrypt middleware to encrypt my password.
Whitout bcrypt I could save the users, but with it not now.
My users.js file
'use strict'
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const bcrypt = require('bcrypt')
const UserSchema = new Schema({
email: { type: String, unique: true, lowercase: true },
displayName: String,
password: { type: String, select: false }
})
UserSchema.pre('save', (next) => {
let user = this
if (!user.isModified('password')) {
return next();
}
bcrypt.genSalt(10, (err, salt) => {
if (err) return next(err)
bcrypt.hash(user.password, salt, null, (err, hash) => {
if (err) return next(err)
user.password = hash
next();
})
})
})
module.exports = mongoose.model('User', UserSchema)
My router.js file:
const express = require('express')
const router = express.Router()
const mongoose = require('mongoose')
const User = require('./model/user')
const bcrypt = require('bcrypt')
router.post('/user', (req, res) => {
console.log(req.body)
let user = new User()
user.email = req.body.email
user.displayName = req.body.displayName
user.password = req.body.password
user.save((err, stored) => {
res.status(200).send({
user: stored
})
})
})
This is the server response:
{}
My db is not affected...
I can see two mistakes in the provided code:
1. this in the pre-save middleware is not a user document instance
Arrow functions do not provide their own this binding:
In arrow functions, this retains the value of the enclosing lexical context's this. [source]
Change your code to the following:
UserSchema.pre('save', function (next) {
const user = this;
// ... code omitted
});
2. Not handling duplicate key MongoError
The request might fail with MongoError: E11000 duplicate key error collection since email field is unique. You are ignoring such fail and since stored in your user.save() is undefined the response from the server is going to be an empty object.
To fix this issue you need to add a handler in the following code:
user.save((err, stored) => {
if (err) {
throw err; // some handling
}
res.status(200).send({user: stored});
});
so hello everyone i'm devolpping my authentication backend i set up my routers my models middlewares and everything then i tried to use postman to see if the registation work or not and each time i click on send request nothing happen i don't know what should i do exactly so please can anyone help with this
database/db.js // connection to database
const mongoose = require('mongoose')
require('dotenv').config();
const base = process.env.MONGO_DATA;
try {
mongoose.connect( base,
{useNewUrlParser: true, useCreateIndex: true}, () =>
console.log("database connected"));
}catch (error) {
console.log("could not connect");
}
models/user.model.js
const mongoose = require('mongoose')
const validator = require('validator')
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const userSchema = mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
unique: true,
lowercase: true,
validate: value => {
if (!validator.isEmail(value)) {
throw new Error({error: 'Invalid Email address'})
}
}
},
password: {
type: String,
required: true,
minLength: 7
},
tokens: [{
token: {
type: String,
required: true
}
}]
})
userSchema.pre('save', async function (next) {
// Hash the password before saving the user model
const user = this
if (user.isModified('password')) {
user.password = await bcrypt.hash(user.password, 8)
}
next()
})
userSchema.methods.generateAuthToken = async function() {
// Generate an auth token for the user
const user = this
const token = jwt.sign({_id: user._id}, process.env.JWT_KEY)
user.tokens = user.tokens.concat({token})
await user.save()
return token
}
userSchema.statics.findByCredentials = async (email, password) => {
// Search for a user by email and password.
const user = await User.findOne({ email} )
if (!user) {
throw new Error({ error: 'Invalid login credentials' })
}
const isPasswordMatch = await bcrypt.compare(password, user.password)
if (!isPasswordMatch) {
throw new Error({ error: 'Invalid login credentials' })
}
return user
}
const User = mongoose.model('User', userSchema)
module.exports = User
controllers/user.js
const express = require('express')
const User = require('../models/user.model')
const router = express.Router()
router.post('/users', async (req, res) => {
// Create a new user
try {
const user = new User(req.body)
await user.save()
const token = await user.generateAuthToken()
res.status(201).send({ user, token })
} catch (error) {
res.status(400).send(error)
}
})
router.post('/users/login', async(req, res) => {
//Login a registered user
try {
const { email, password } = req.body
const user = await User.findByCredentials(email, password)
if (!user) {
return res.status(401).send({error: 'Login failed! Check authentication credentials'})
}
const token = await user.generateAuthToken()
res.send({ user, token })
} catch (error) {
res.status(400).send(error)
}
})
module.exports = router
index.js
require('dotenv').config()
const express = require('express')
const userRouter = require('./src/routers/user')
const port = process.env.PORT
require('./src/database/db')
const app = express()
app.use(express.json())
app.use(userRouter)
app.listen(port, () => {
console.log(`Server running on port ${port}`)
})
so each time i try to see if i'm signed up or not postman didn't give any response he keep saying <> and no result can someone help me please ?
Have you created " data " and " db " folder in your ' C ' drive?
Here are the steps:
Create a folder on your machine with name mongodb
Create a folder with name data in the mongodb folder
Create one more folder with name db in the data folder
For more, refer here
When i wanna save a user with this code:
const router = require("express").Router();
const User = require("../model/User");
//validate
const joi = require("#hapi/joi");
const schema = joi.object({
name: joi.string().min(1).max(255).required(),
email: joi.string().max(255).email().required(),
password: joi.string().min(8).max(255).required(),
});
router.post("/register", async (request, respond) => {
const { error } = schema.validate(request.body);
if (error) return respond.status(400).send(error.details[0].message);
const user = new User({
name: request.body.name,
email: request.body.email,
password: request.body.password,
});
try {
const savedUser = await user.save();
respond.send(savedUser);
} catch (err) {
respond.status(500).send(err);
}
});
module.exports = router;
it doesnt get any error but it also does not respond anything and does not save anything
I don't see any client connection in your code. Don't forget to connect to your mongoDB server and open your connection before processing any operation. Otherwise it won't have any effect.
var db = new Db('test', new Server('localhost', 27017));
// Establish connection to db
db.open((err, db) => {
// Do what you want
});
See this example of saving a document in nodeJS: Save to MongoDB
MongoDB inserts document without properties(look at the bottom of the post to see how my collection looks like).I'm using postman to test my db when I try to insert the following:
{
"username":"JohnDoe",
"password" : "123456"
}
I'm building a MEAN stack application.Also, I noticed if I set the properties to be required, postman tells me that it Failed to register user. That's why I comment it out, but even without it and getting a postive response I still get empty documents in my collection.
Postman tells me:
{
"success": true,
"msg": "User registered"
}
My user.js file
const bcrypt = require ('bcryptjs');
const config = require ('../config/database');
//UserSchema
const UserSchema = mongoose.Schema({
username: {
type: String,
//required: true
},
password: {
type: String,
//required: true
}
});
const User = module.exports = mongoose.model("User", UserSchema);
//To user function outside
module.exports.getUserById = function(id, callback){
User.findById(id,callback);
}
module.exports.getUserByUsername= function(username, callback){
const query = {username: username}
User.findOne (query,callback);
}
User.addUser = function (newUser, callback) {
bcrypt.genSalt(10, (err, salt) =>{
bcrypt.hash(newUser.password, salt, (err, hash) => {
newUser.password = hash;
newUser.save(callback);
});
});
}
My users.js file:
const express = require('express');
const router = express.Router();
const passport = require('passport');
const jwt = require('jsonwebtoken');
const User = require('../modules/user');
// Register
router.post('/register', (req, res, next) => {
let newUser = new User({
username: req.body.username,
password: req.body.password
});
User.addUser(newUser, (err, user) => {
if(err){
res.json({success: false, msg:'Failed to register user'});
} else {
res.json({success: true, msg:'User registered'});
}
});
});
module.exports = router;
What I see in my collection:
{
"_id": {
"$oid": "5937b36bafdd733088cb27d0"
},
"__v": 0
}
You should learn about what is mongoose statics and methods.
In User model you should be declaring the functions as methods and statics based on the way you want it.
const bcrypt = require ('bcryptjs');
const config = require ('../config/database');
//UserSchema
const UserSchema = mongoose.Schema({
username: {
type: String,
//required: true
},
password: {
type: String,
//required: true
}
});
//To user function outside
UserSchema.statics.getUserById = function(id, callback){
User.findById(id,callback);
}
UserSchema.statics.getUserByUsername= function(username, callback){
const query = {username: username}
User.findOne (query,callback);
}
UserSchema.methods.addUser = function (callback) {
bcrypt.genSalt(10, (err, salt) =>{
bcrypt.hash(newUser.password, salt, (err, hash) => {
this.password = hash;
this.save(callback);
});
});
}
exports.User = mongoose.model("User", UserSchema);
In your controller user file, you should use addUser with your instance of the User model not on the Model you exporting. Check below..
const express = require('express');
const router = express.Router();
const passport = require('passport');
const jwt = require('jsonwebtoken');
const User = require('../modules/user');
// Register
router.post('/register', (req, res, next) => {
let newUser = new User({
username: req.body.username,
password: req.body.password
});
newUser.addUser(function(err, user) => {
if(err){
res.json({success: false, msg:'Failed to register user'});
} else {
res.json({success: true, msg:'User registered'});
}
});
});
module.exports = router;