User.save to DB (use mongoose) is not a function - node.js

UserModelVk.findOne({vkontakteId: profile.id}, function(err, vkUser){
if(err){ return done(err) }
if(!vkUser){
const user = new UserModelVk({
vkontakteId: profile.id,
name: profile.displayName,
access_token: params.access_token
})
user.save(function(err) {
if (err){ log.error(err) }
localStorage.setItem('username', user.vkontakteId);
localStorage.setItem('key', user.access_token)
return done(err, user);
});
} else {
vkUser = { access_token: params.access_token }
vkUser.save(function(err) {
if (err){ log.error(err) }
localStorage.setItem('key', vkUser.access_token)
return done(err, vkUser);
});
localStorage.setItem('username', vkUser.vkontakteId);
return done(err, vkUser);
}
})
Here, I check have user in my DB or not. If not: register user (and send to him his token), if have: update token (and send to him his updated token).
Why ".save is not a function"?
P.S: And how correctly send data to user localStorage?

You are overriding vkUser by assigning it vkUser = { access_token: params.access_token }. The save function is lost therefore.
Change it to:
vkUser.access_token = params.access_token

Related

Can I deserialize the different users like student and admin in passport.js?

In passport js authentication when the deserialize the user I have the following doubt?
Can I use different Login tables to fetch the user ?(depends on they are admin or student like that)
But I was try to implement it by using if statement that was won't work it which mean cannot fetch from db. What I am doing that any help !
Using LocalStrategy u can use it. Here you have to make two different calls to check.
Sample:
passport.use(new LocalStrategy(
function(username, password, done) {
async.parallel([
function(cb){
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return cb(null, user);
});
},
function(cb){
Admin.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return cb(null, user);
});
}
], ([res1, res2]) => {
// on result
done(null, res1)
// OR
done(null, res1)
})
}
));

How to disallow disabled users from logging in, into a page using passport.js?

I've used a soft delete feature in mongodB to disable a user and not delete it permanently. Now, only enabled users can log in to the site while the disabled users can not log in to the site.
// Soft delete feature
exports.getDisabledUsers = function(req,res, next) {
User.find({active: false}, function(err, users) {
if (err) {
res.send(err);
}
res.json(users);
});
}
// Log In
exports.login = function (req, res, next) {
var userInfo = setUserInfo(req.user);
res.status(200).json({
token: 'JWT ' + generateToken(userInfo),
user: userInfo
});
};
// Passport.js
var localLogin = new LocalStrategy(localOptions, function (email, password, done) {
User.findOne({
email: email
}, function (err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, {
error: 'Login failed. Please try again.'
});
}
user.comparePassword(password, function (err, isMatch) {
if (err) {
return done(err);
}
if (!isMatch) {
return done(null, false, {
error: 'Login failed. Please try again.'
});
}
return done(null, user);
});
});
});
Disabled users shouldn't be able to log in. Right now, they are able to log in.
While Disabling the user you can move that data to another collection, that way your disabled user cannot be able to login to your system
exports.disableUser = function (req, res, next) {
User.findByIdAndUpdate({_id:req.params._id}, {active: false}, function (err, users) {
if (err) {
res.send(err);
}
User.findByIdAndRemove(
{_id:req.params._id},
function(err, doc) {
if (doc) {
DisableUser.insertMany(doc, function(err, doc){
// your response
});
} else {
// your response
}
)
});
}
You have not checked user status is active or not. This can be done by adding a condition in code, or modifying mongo query and adding one more condition in findOne.
//CODE
if(!user.active) {
//RETURN USER IS NOT ACTIVE
}
//MONGO QUERY
User.findOne({
email: email,
active: true
}, function (err, user) {
//YOUR CODE
}
Role based login may create some complexity but this can be achieved simply by adding one more collection named disabledUsers
when admin disable any user then the click function do two things at the same time
1)add the email into disabledUser collection
2)delete the user from user collection
Then in your login function just check this way
disabledUser.findOne({email :email },
function (err ,user){
if(err) return done(err)
else{
if(!user){
user.findOne({email : email }
write your login stuff here the wau you r doing
}
else{return alert('user is disabled')}
}
})

Node: Control flow, Can't save FB friends to db with mongoose

first off thank you for your help. I am trying to make a call to the facebook api to gather all of my users friends.
passport.use(new FacebookStrategy({
clientID: config.fb.id,
clientSecret: config.fb.secret,
callbackURL: "http://localhost:3000/auth/facebook/callback"
},
function(accessToken, refreshToken, profile, done) {
User.findOne({
"facebook.id" : profile.id
}, function(err, user) {
if (err) {
return done(err);
}
//No user was found... so create a new user with values from Facebook (all the profile. stuff)
if (!user) {
this is the call back I am made to return the data
function viewback(err, data, user) {
if(err) {
console.log("Error: " + JSON.stringify(err));
} else {
return data;
}
}
below is where I am making the call for friends, the data variable is not getting set before the call to create the user is being completed and it is not saving the data.
var fbapi = require('facebook-api');
var client = fbapi.user(accessToken); // do not set an access token
process.nextTick(function(){
var data = client.me.friends(viewback);
});
user = new User({
name: profile.displayName,
username: profile.username,
profileUrl: profile.profileUrl,
provider: 'facebook',
token: accessToken,
//now in the future searching on User.findOne({'facebook.id': profile.id } will match because of this next line
facebook: profile._json
fb_friends: data
});
user.save(function(err) {
if (err) console.log(err);
console.log('making a new user')
return done(err, user);
});
} else {
//found user. Return
console.log('found the user')
return done(err, user);
}
});
}));
I don't receive any errors and the user saves in the DB, but without the friend data. Any help would be great. Even better would be something I could read to pick up on this concept.

Facebook OAuth creates new user each time using Passport and Express

I am using the Passport node module in conjunction with Express to enable users to login via Facebook, Twitter, and Google. I have setup Facebook and Twitter so far and users can login successfully, but it creates a new user every time even though I have tried to make it recognize when a user has already created an account. Here is the code I am using:
passport.use(new FacebookStrategy({
clientID: '********************',
clientSecret: '***********************',
callbackURL: "http://www.wundertutor.com:3000/auth/facebook/callback"
}, function(accessToken, refreshToken, profile, done) {
processProfile(profile, function(err, user) {
if (err) throw err;
done(null, user);
});
}));
function processProfile(profile, callback) {
if (profile.emails) {
profile.emails.forEach(function(email) {
findUserByEmail(email.value, function(err, user) {
if (user) {
return callback(null, user);
}
});
});
var newUser = {
id: profile.id,
firstName: profile.name.givenName,
lastName: profile.name.familyName,
email: profile.emails[0].value
};
user.create(newUser, profile.provider, function(err, user) {
if (err) throw err;
return callback(null, user);
});
}
}
function findUserByID(id, callback) {
pool.getConnection(function(err, connection) {
var query = connection.query("SELECT * FROM users WHERE id = ?", id, function(err, rows) {
connection.end();
var user;
if (rows.length == 1) {
user = {
id: rows[0].id,
role: rows[0].role,
firstName: rows[0].firstName,
lastName: rows[0].lastName,
email: rows[0].email
};
}
return callback(null, user);
});
});
}
function findUserByEmail(email, callback) {
if (email) {
pool.getConnection(function(err, connection) {
if (err) throw err;
var query = connection.query('SELECT * FROM users WHERE email = ?', email, function(err, rows) {
connection.end();
if (err) throw err;
if (rows.length == 1) {
console.log("C");
return callback(null, rows[0]);
} else {
return callback(null, null);
}
});
});
} else {
return callback(null, null);
}
}
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
findUserByID(id, function(err, user) {
done(null, user);
});
});
In processProfile, I have it loop through each email associated with a user profile and check to see whether that user is already in our database. If they are, then it gets that user's info and passes it to the 'done' callback to be serialized and log the user in. The strange thing is that when a user who is already in our database is logged in, it does get to this part of the code and returns the user successfully (determined by a series of console.logs), but for some reason it still creates a new user in the database each time they try to log in.
Also, on a side note, when I log in normally (via username and password), I am redirected to our learn page '/learn', but when I log in via Facebook, I am redirected to the learn page with some extra stuff afterwards '/learn#='. Any ideas?
Try rewriting your processProfile function to something like this:
function processProfile(profile, callback) {
var result;
if (profile.emails) {
profile.emails.forEach(function(email) {
findUserByEmail(email.value, function(err, user) {
if (user) {
result = user;
}
});
});
if( !user ) {
var newUser = {
id: profile.id,
firstName: profile.name.givenName,
lastName: profile.name.familyName,
email: profile.emails[0].value
};
user.create(newUser, profile.provider, function(err, user) {
if (err) throw err;
result = user;
callback( null, result );
});
} else {
callback( null, result );
}
}
}

mongodb and authenticate and passport in node.js

i have a collection like this in mongodb
{
username:silver,
Email:sil#gmail.com,
password:silvester,
}
so to authenticate i will fetch data from database and then i will check given email is exist or not with if statement like this
app.post("/login",function(req,res){
var email=req.body['emailid'];
collection.find({email:sil#gmail.com}).toArray(function(err,res)
{
if(res.length==0){
console.log("name is not exist");
}else{
if(res.email==email){
console.log("email is exist");
}else{
console.log("not exist");
}
}
});
});
so here how to use passport module for authentication.let me know it with sample code with configuration.
i am using express3.x framework .so how to configure it also.
Here you can read about local strategies, and here about configure.
Your local strategy should look like this:
passport.use(new LocalStrategy({
emailField: 'email',
passwordField: 'passw',
},
function (emailField, passwordField, done) {
process.nextTick(function () {
db.collection(dbCollection, function (error, collection) {
if (!error) {
collection.findOne({
'email': sil#gmail.com
'password': silvester // use there some crypto function
}, function (err, user) {
if (err) {
return done(err);
}
if (!user) {
console.log('this email does not exist');
return done(null, false);
}
return done(null, user);
});
} else {
console.log(5, 'DB error');
}
});
});
}));

Resources