So, here's my user schema where i declared hello method onto the Userschema which im using to test
//user.model.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
username: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3
},
password: { type: String, required: true }
});
UserSchema.methods.hello = () => {
console.log("hello from method");
};
const User = mongoose.model("User", UserSchema);
module.exports = User;
here's routes file
//authroutes.js
const router = require("express").Router();
let User = require("../models/user.model");
router.route("/").get((req, res) => {
res.send("auth route");
});
router.route("/signup").post((req, res) => {
const username = req.body.username;
const password = req.body.password;
const newUser = new User({
username,
password
});
newUser
.save()
.then(() => res.json(`${username} added`))
.catch(err => console.log(err));
});
router.route("/login").post(async (req, res) => {
await User.find({ username: req.body.username }, function(err, user) {
if (err) throw err;
//this doesnt work
user.hello();
res.end();
});
});
module.exports = router;
in the login route im calling hello function to test but that doesnt work and throws this error
TypeError: user.hello is not a function
You need to use User.findOne instead of User.find, because find returns an array, but what we need is an instance of the model.
Also Instance methods shouldn't be declared using ES6 arrow functions.
Arrow functions explicitly prevent binding this, so your method will not have access to the document and it will not work.
So you had better to update method like this:
UserSchema.methods.hello = function() {
console.log("hello from method");
};
Related
I am unable to write the correct query.
I am trying to check if the user already exists in the database and it will respond in Login Successfully Response.
This code is in working position problem lies in Query.
I hope somebody will help
function login() {
app.post("/login/", async(req, res) => {
const query = new Model({
email: req.body.email,
password: req.body.password,
});
const cursor = Model.find(query); // (*Here's the problem*)
console.log(cursor);
if (query === cursor) {**strong text**
console.log(query);
res.send("login successfully");
} else {
console.log(query);
res.send("user does not exist ");
}
});
}
login();
// Model and Schema
const LoginSchema = new mongoose.Schema({
email: { type: String, required: true },
password: { type: String, required: true },
});
const Model = mongoose.model("login_details", LoginSchema);
// Registeration Phase
function registration() {
app.post("/register/", async(req, res) => {
const model = new Model({
email: req.body.email,
password: req.body.password,
});
const result = await model.save();
console.log(result);
res.send(model);
});
}
// Headers
const express = require("express");
const app = express();
const mongoose = require("mongoose");
app.use(express.json());
app.use(express.urlencoded({ extend: true }));
//
Issues with your code
1- You don't need to use new Model({}) to query
2- You're using .find() which returns an array, use findOne() instead
3- You're attempting to check if a mongoose model (with _id) equals a query without the _id which won't work
4- Use return at the end of your function (won't affect the functionality here but just as good practice not to encounter errors like cannot set headers after they're sent)
possible solution
function login() {
app.post("/login/", async (req, res) => {
const cursor = await Model.findOne({
email: req.body.email,
password: req.body.password,
});
console.log(cursor);
if (cursor) {
console.log(cursor);
return res.send("login successfully");
} else {
return res.send("user does not exist ");
}
});
}
You are using Mongoose in the wrong way. Try this.
const result = await Model.find({
email: req.body.email,
password: req.body.password,
});
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});
});
I created a small project with node+express+mongodb
This is where i call the create user:
const express = require("express");
const User = require("../models/user");
const router = express.Router();
router.post("/register", async (req, res) => {
try {
const user = await User.create(req.body);
return res.send({ user });
} catch (e) {
return res.status(400).send({ error: "Registration failed" });
}
});
module.exports = app => app.use("/auth", router);
and here is the Schema for the user:
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
name: {
type: String,
require: true
},
email: {
type: String,
require: true,
unique: true,
lowercase: true
},
password: {
type: String,
require: true,
select: false
},
createdAt: {
type: Date,
default: Date.now
}
});
const User = mongoose.model("User", UserSchema);
module.exports = User;
But when o make the resquest, it nevers get a response, it waits forever. And when o take out the await from the request, it gets an empty response { "user": {}}
I'm kind lost looking the mongoose documentation (the ideia is to make a simple rest api, i'm used with python, but looking to learn node)
You have to create a new user from User Model as follows:
const express = require("express");
const User = require("../models/user");
const router = express.Router();
router.post("/register", async (req, res) => {
try {
var user = new User(request.body);
var result = await user.create();
return res.send({ result });
} catch (e) {
return res.status(400).send({ error: "Registration failed" });
}
});
module.exports = app => app.use("/auth", router);
I've come across a blocker on attempting to promisify a mongoose method.
As far as my understanding goes I should be able to promisify fn's that take in callbacks with an error and a parameter, but in this case I get this error:
TypeError: this.Query is not a constructor
model code:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
module.exports = mongoose.model('User', new Schema({
name: String,
password: String,
admin: Boolean
}));
breaking code:
var User = require('./app/models/user');
var { promisify } = require('util');
var findUserPromise = promisify(User.findOne);
...
findUserPromise({ name: req.body.name })
.then(user => console.log("do something with the user"))
.catch(err => { console.log("err ", err) });
Any help is very much appreciated!
mongoose is already very promise-friendly. To get a promise from findOne(), you just need to call .exec():
Instead of
var findUserPromise = promisify(User.findOne);
...
findUserPromise({ name: req.body.name })
.then(user =>
...
Just call it with .exec()
:
User.findOne({ name: req.body.name }).exec()
.then(user =>
...
Yes as #Jim B answer, mongoose is promise friendly. you can also use async and await
const User = require('./app/models/user');
module.export = {
userDetails: async (req, res, next) => {
try {
const user = await User.findOne({ name: req.body.name });
console.log(user);
}
catch(err) {
console.log(err);
}
}
}
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;