I have created the custom user with base User and i am searching the following email exist in db or not , if email exist then don't create it and log the access token .
module.exports = function (User) {
let app = require('../../server/server');
var loopback = require('loopback');
var credentials = { email: 'foo#foo.com', password: 'password' };
var filter = {
'where': {
'email': credentials.email
}
};
loopback.User.findOrCreate(filter, credentials, function (err) {
if (err) throw err;
User.login(credentials, function (err, token) {
if (err) throw err;
console.log(token);
process.exit();
});
});
Error:
Error: Cannot call User.findOrCreate(). The findOrCreate method has not been setup. The PersistedModel has not been correctly attached to a DataSource!
Try checking your Datasource configuration and see if it's properly connected to the Database.
Just try by
User.findOrCreate(filter, credentials, function (err) { });
As in Loopback doc
PersistedModel.findOrCreate([filter], data, callback)
Reference Link : https://apidocs.strongloop.com/loopback/#persistedmodel-findorcreate
Related
I have the following web service that we have created.
router.post('/register', (req, res) => {
const user = req.body;
// registerSchema.validate(user, registerSchema, (err, result) => {
// if (err)
// res.status(500).end(err.message);
// });
findUserByEmail(user.email, (err, userFeedback) => {
console.log('Fired.');
if (userFeedback)
res.status(500).end(JSON.stringify("User already exists"));
});
const passwordPromise = util.promisify(bcrypt.hashSync);
const pass = bcrypt.hashSync(user.password);
createUser(user.name, user.email, pass, [], (err) => {
if (err)
res.status(418).end(JSON.stringify("Failed to create user."));
});
res.status(200).end(JSON.stringify("Signup successful."));
});
We are using this to register a user. Here are the methods we are calling in this part of the web service.
function createUser (userName, userEmail, userPass, dev, cb) {
var mg = require('mongodb').MongoClient;
mg.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, function(err, db){
var dbo = db.db(myDB);
var user = { name: userName,
email: userEmail,
password: userPass,
devices: dev };
var insert = util.promisify(dbo.collection("Users").insertOne);
dbo.collection("Users").insertOne(user, function(err, res) {
if (err) throw err;
console.log(`${user.name} has been added.`);
db.close();
sendEmail(userEmail,
'The CRUST Company welcomes you!',
'Thank you for signing up for our services!' );
});
});
}
//See if a user exists
function findUserByEmail (userEmail) {
var mg = require('mongodb').MongoClient;
mg.connect(url, { useNewUrlParser: true, useUnifiedTopology: true },
function(err, db){
var dbo = db.db(myDB);
var query = { email : userEmail };
var find = util.promisify(dbo.collection("Users").find);
return dbo.collection("Users").find(query).toArray(function(err, result) {
if (err) throw err;
db.close();
});
});
}
The createUser seems to be working fine but the FindUserByEmail is not firing at all. We even tried console.log within the method and got no response. Any ideas on why this method may not be firing? Thx
Your calling code passes findUserByEmail() a callback function:
findUserByEmail(user.email, (err, userFeedback) => {
console.log('Fired.');
if (userFeedback)
res.status(500).end(JSON.stringify("User already exists"));
});
But, your actual implementation of that function doesn't accept a callback and thus never calls it so of course the callback you pass never gets called.
Also, there are multiple asynchronous design problems. You are treating asynchronous operations like they are blocking. They are not. You must continue the flow of your code INSIDE the callback function, not after the function call which you do correctly inside of findUserByEmail() but do not do correctly in your request handler where you call it.
Also, createUser() declares a callback as an argument, but never calls it so the callback you pass to createUser() will also never get called.
I'm trying to hash the password of admin in my site. I have searched and found out that this error is because of being null or undefined the value that we want to hash it.
here is my code, whenever I console.log(admin) it returns {}, I don't know why.
adminSchema.pre('save', (next) => {
var admin = this;
console.log(admin)
bcrypt.hash(admin.password, 10, (err, hash) => {
if (err) return next(err);
admin.password = hash;
next();
});
});
var adminModel = mongoose.model('Admin', adminSchema);
module.exports = adminModel;
server side code:
var adminModel = require('./../models/admins');
router.post('/register', (req, res) => {
var newAdmin = {
adminName: req.body.adminName,
faculty: req.body.faculty,
email: req.body.email,
password: req.body.password
}
adminModel.create(newAdmin, (err, admin) => {
if (err) {
console.log('[Admin Registration]: ' + err);
}
else {
console.log('[Admin Registration]: Done');
req.session.adminId = admin._id;
res.redirect('/admin/submitScore')
}
})
});
Unfortunately, I can't find the reason of that the console.log(admin) is empty. I would be thankful if anyone could help me.
The keyword this changes scope when used in arrow functions. See more here. This is not a problem in your express route, but in your mongoose middleware it is. Change your function to not use this or make an old fashioned function(){}
I am using passportjs to handle auth of my app.
Once the user is logged in, I want to add the possibility to change the password from inside the app.
this is in my controller:
$http.post('/change-my-password',{oldPassword: $scope.user.oldpassword, newPassword: $scope.user.newpassword})
.then(function (res) {
if (res.data.success) {
// password has been changed.
} else {
// old password was wrong.
}
});
and this is my route handler in express nodejs in backend:
router.post('/change-my-password', function (req, res) {
if (!req.isAuthenticated()) {
return res.status(403).json({
success: false
});
}
UserSchema.findById(req.user._id, function(err, user){
if (err) return res.status(200).json({success: false});
user.validatePassword(req.body.oldPassword, function(err) {
if (err){
return res.status(200).json({
success: false
});
}
user.setPassword(req.body.newPassword, function() {
if (err || !user) {
return res.status(200).json(
{
success: false
}
)
}
user.save(function(err) {
if (err) return res.status(200).json({success: false});
req.login(user, function (err) {
if (err) return res.status(200).json({success: false});
return res.status(200).json({success: true});
});
});
});
});
});
});
here is my user schema model:
// user model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var passportLocalMongoose = require('passport-local-mongoose');
var bcrypt = require('bcrypt-nodejs');
var UserSchema = new Schema({
email: String,
password: String,
confirmStatus: Boolean,
token: String,
registerAt: Number
});
UserSchema.methods.validatePassword = function (password, callback) {
this.authenticate(password, callback);
};
UserSchema.plugin(passportLocalMongoose,
{
usernameField: 'email'
});
module.exports = mongoose.model('users', UserSchema);
the problem:
I find my user by Id in my mongoose schema UserSchema then I should check if the oldPassword is valid or not, and then I set the new password.
I successfully find the user and the set the new password. But the part that should check for comparison of the old password field, doesn't work at all. Whatever I enter in the old password field gets accepts as OK and that step is skipped. Whereas, it should throws an error saying that the old password is wrong.
I am also advised to use sanitizedUser in order not to show my salt and etc.
Question is: how can I first do the comparison check of the old password and then do the set new password step? If possible, how can I use the sanitize? And how can I check if the user is not entering the same password as the new password? or if possible, saying that the new password is very similar to the old one?
You can implement the it using the new feature added 3 days ago:
just use the changePassword method, and it handles it through this:
schema.methods.changePassword = function(oldPassword, newPassword, cb) {
if (!oldPassword || !newPassword) {
return cb(new errors.MissingPasswordError(options.errorMessages.MissingPasswordError));
}
var self = this;
this.authenticate(oldPassword, function(err, authenticated) {
if (err) { return cb(err); }
if (!authenticated) {
return cb(new errors.IncorrectPasswordError(options.errorMessages.IncorrectPasswordError));
}
self.setPassword(newPassword, function(setPasswordErr, user) {
if (setPasswordErr) { return cb(setPasswordErr); }
self.save(function(saveErr) {
if (saveErr) { return cb(saveErr); }
cb(null, user);
});
});
});
};
so in your code, you need to replace the validatePassword method by this:
user.changePassword(req.body.oldPassword,req.body.newPassword, function(err) {
if (err){
return res.status(200).json({
success: false
});
}
hope this works for you.
Hi All,
I am authenticating my user using bcrypt module.
I am able to do perform the Registration process, but facing problem during Login process.
User Model:
var userSchema = new Schema({
email: {type: String, required: true},
password: {type: String,
});
Hashing methods:
userSchema.methods.encryptPassword = function (password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(5), null)
};
userSchema.methods.validPassword = function (password) {
return bcrypt.compareSync(password, this.password);
};
Sign in:
module.exports.login = function (user, callback) {
User.findOne({'email': user.email, 'password': user.validPassword(this.password)}, callback);
};
Login Route
router.post('/login', function (req, res) {
var user = req.body;
User.login(user, function (err, user) {
if (err) {
throw err;
}
if (!user) {
res.sendStatus(404);
return;
}
res.json(user.id);
});
});
While executing am getting this error: TypeError:user.validPassword is not a function
Please Help.
Your mistake is that the user being provided to your login method is not a Mongoose DB object. Instead, your login function should look something like this:
module.exports.login = function (request, callback) {
User.findOne({'email': request.email }, function(err, user) {
if (err) return callback(err);
if(!user || !user.validPassword(request.password)) return callback();
return callback(null, user);
});
};
This will ensure that user is a valid Mongoose object before you attempt to verify the password.
One other possible solution, if you'd prefer to avoid checking that the password is valid in your data layer, is to simply fetch the user document based on its email and then check the password in the login route.
router.post('/login', function (req, res) {
var user = req.body;
User.findOne(user, function (err, user) {
if (err) {
throw err;
}
if (!user) {
res.sendStatus(404);
return;
}
if (!user.validPassword(req.body.password)) {
res.sendStatus(401);
return;
}
res.json(user.id);
});
});
In Login Route, you need to instantiate the Schema:
router.post('/login', function (req, res) {
var user = new User(req.body);
User.login(user, function (err, user) {
if (err) {
throw err;
}
if (!user) {
res.sendStatus(404);
return;
}
res.json(user.id);
});
});
With the following controller, how can I call one method from another in the same controller?
Specifically, calling login() within a successful signup(), while retaining the same functionality for login() when it is used by a form?
The line this.login(newUser) does not work, nor does plain old login(newUser)
In both scenarios, I get the error:
TypeError: Cannot call method 'login' of undefined
var mongoskin = require('mongoskin');
module.exports = {
login: (function (req, res) {
req.db.collection('auth').findOne({_id: mongoskin.helper.toObjectID(req.body.id)},
function (err, results) {
// log person in and send results to client
}
)
}),
signup: (function (req, res) {
var user = req.body;
req.db.collection('auth').insert(user, function (err, newUser) {
// after adding user, automatically log them in
// does not work:
//login(newUser, function (err) {
// do something
//})
// does not work:
this.login(newUser, function (err) {
// do something
})
}
)
})
}
Controllers should be doing as little as possible, and should orchestrate the work required by executing functions stored elsewhere.
View this gist - click here
What I have done is created "services" that are not tied to the client request, therefore re-usable everywhere.
Hope this helps.
Thanks to Dave Newton
var mongoskin = require('mongoskin');
var myCollection = 'auth';
Solution
function localLogin(db, myCollection, user, res){
db.collection(myCollection).findOne({_id: mongoskin.helper.toObjectID(user._id)},
function(err, user){
res.send({ token: createToken(user) });
});
module.exports = {
login: (function (req, res) {
var user = req.body;
localLogin(req.db, myCollection, user, res)
},
signup: (function (req, res) {
var user = req.body;
req.db.collection(myCollection).insert(user, function (err, newUser) {
// after adding user, automatically log them in
localLogin(req.db, myCollection, newUser, res)
})
}
) }) }