auth0 Custom Database Action Script - How to access user_id? - mongodb

I'm using auth0, I'm making a script on create under Action Scripts to save user to my mongoDB database. I only need to save the email and user_id, but I can't find the user_id?
Code is below, but the user only returns: {"tenant":"tenant-name","connection":"MongoDB-MainDB","email":"xxx","password":"xxx","debug":true}
Here is my code (This is basically the sample code provided by auth0):
function create (user, callback) {
mongo('mongodb://xxx', function (db) {
var users = db.collection('users');
users.findOne({ email: user.email }, function (err, withSameMail) {
if (err) return callback(err);
if (withSameMail) return callback(new Error('the user already exists'));
else {
users.insert({ "_id" : user.user_id, "email" : user.email}, function (err) {
if (err) return callback(err);
callback(new Error(JSON.stringify(user)))
});
}
});
});
}
auth0 tutorial for reference: https://auth0.com/docs/connections/database/custom-db

Related

Understanding session in sailsJs with Passport

I have had many problems, when I want to get information from user model. I read some solutions, but I didnt understand.
This is my code:
* AuthController
var passport = require('passport');
module.exports = {
_config: {
actions: false,
shortcuts: false,
rest: false
},
login: function(req, res) {
passport.authenticate('local', function(err, user, info) {
if ((err) || (!user)) {
return res.send({
message: info.message,
user: user
});
}
req.logIn(user, function(err) {
if (err) res.send(err);
return res.send({
message: info.message,
user: user
});
});
})(req, res);
},
logout: function(req, res) {
req.logout();
res.redirect('/');
},
signup: function (req, res) {
var data = req.allParams();
User.create({email:data.email,password:data.password,name:data.name}).exec(function(error,user){
if(error) return res.negotiate(err);
if(!user)return res.negotiate(err);
return res.ok();
});
}
};
*view
<h1>List of my dates</h1>
<h1><%= email %></h1>
<h1><%= req.user.name %></h1>
*model
attributes: {
email: {
type: 'email',
required: true,
unique: true
},
password: {
type: 'string',
minLength: 6,
required: true
},
toJSON: function() {
var obj = this.toObject();
delete obj.password;
return obj;
}
},
beforeCreate: function(user, cb) {
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) {
console.log(err);
cb(err);
} else {
user.password = hash;
cb();
}
});
});
}
};
Only works if I use res.render('view', {email: req.user.email}) but, I would like to use the user data in many views. I cant write methods with Current user params, becouse dont work.
Thanks.
It is unclear to me what your actual problem is or what the question actually is but I will try to help.
Look here:
login: function(req, res) {
passport.authenticate('local', function(err, user, info) {
if ((err) || (!user)) {
return res.send({
message: info.message,
user: user
});
}
...
})(req, res);
},
There you are adding data (locals) to the ejs and the values are message and user so in the ejs you must reference it as this, so you will use user.name and not req.user.name? I'm not sure why you're binding the (req, res) either.
It's confusing because your ejs uses the email value but I don't see it there as a local so maybe thats your problem, it must be defined?
Consider the following simple example:
// User Controller
// GET request /signin
// The signin form
signin(req, res) {
// Load the view from app/views/*
return res.view('signin', {
title: 'Sign In'
});
},
// POST request to /signin
// This was posted from the signin form
// Use io.socket.post(...) to do this from the signin form
// Can use window.location.replace('/account') on successful request
authenticate(req, res) {
// The data posted, email and password attempt
var data = req.allParams();
// Does it match?
User.findOne({
email: data.email,
// This is stupid, don't ever use plain text passwords
password: data.password
})
.exec(function(err, user) {
// Server related error?
if (err) res.serverError(err.message);
// No user was found
if (!user) res.badRequest('Username or password not found');
// Sign the user in
req.session.userId = user.id;
// User was found
res.ok();
});
},
// GET request to /account
// Displays the users information
// Can use policies to ensure that only an authenticated user may access their own account information
account(req, res) {
// If the user is not signed in
// This is an alternative to using the sails policy isLoggedIn
if (!req.session.userId) res.redirect('/signin');
// Get the users details
User.findOne({
id: req.session.userId
})
.exec(function(err, user) {
// Server related error?
if (err) res.serverError(err.message);
// No user was found
if (!user) res.redirect('/signin');
// Load the ejs file that displays the users information
return res.view('account/index', {
title: 'Account Information',
user: user
});
});
},
// Account View
<p>Email: {{user.email}}</p>
<p>Password: {{user.password}}</p>
Check this out if you want to deal with password encryption: http://node-machine.org/machinepack-passwords
And this if you want to deal with the strength tests (when the user sets the password): https://www.npmjs.com/package/owasp-password-strength-test
This is as passport seems overkill if you're only doing local authentication?

Rollback Transaction for Multiple Models in Waterline ODM in Sails (For Mongo DB )

I am using Sails and Waterline ORM with Mongo Database .
I have two models User and Profile with One to One relationship.
Below is the code I've written for Transaction with Rollback logic. I think there can be a much better logic than this as the current logic is very clumsy.
Questions :
Does Waterline or Sails provide any functionality for Rollback purpose?
Is there any better way of doing this ?
User.create(newUser).then(function (data) {
var newProfile = {
displayName: data.name,
email: data.email,
user: data._id
}
return Profile.create(newProfile);
}).then(function (profileData) {
sails.log.info("Profile Data " + JSON.stringify(profileData));
// Update the user with Profile Info
User.update(newUser._id, {profile: profileData._id}).then(function (updatedUser) {
return updatedUser;
}, function (err) {
// TODO Rollback logic if the User Updation Fails
})
}, function (err) {
sails.log.error("Failed to Create Profile for the User . Deleting the created User");
var criteria = {
email: data.email
}
User.destroy(criteria).then(function (user) {
sails.log.error("Deleted the Created User " + JSON.stringify(user));
throw new Error("ERROR CREATING User");
}, function (err) {
sails.log.error("ERROR DELETING USER");
throw new Error("ERROR DELETING USER", err);
})
});
To question 1 : no.
I would be tempted to do something like this:
async.waterfall([
function(callback){
User.create(newUser).then(function(data){
callback(null, data);
})
.catch(function(err){
callback(err, null, null); // don't need to rollback anything
})
},
function(data, callback){
Profile.create({
displayName: data.name,
email: data.email,
user: data._id
})
.then(function(profile){
callback(null, data, profile)
})
.create(function(err){
callback(err, data._id, null); // only need user's id
})
},
function(userData, profileData, callback){
User.update(userData._id, {profile: profileData._id})
.then(function(updatedUser){
callback(null, updatedUser);
})
.catch(function(err){
callback(err, userData._id, profileData._id); // can roll back both
})
}
], function(err, userData, profileData){
if(err) {
sails.log.error(err);
// do rollback, userData is user's ID, profileData is profile id
// if either one is undefined, then it doesn't exist
} else {
// userData is user object from the last update, return it!
}
})
I don't know if it is better, but it seems more readable, and it handles the errors for any of the three writing phases.

Mongo query always returns the value exists in database, when it does not

I am trying to query for a name field in mongodb and with the following code I always get the response that the value is a duplicate.
var checkUserName = function (userName, email, res){
User.findOne({ name : userName }, function () {
if(userName && typeof userName !== 'undefined'){
res.send("duplicate");
}else{
checkEmail(email);
}
});
}
you are currently ignoring the answer from the database completely and are just checking your input again. This cannot work. Mongoose returns the answer of the query as the second parameter of the callback function (the first is always there to signal errors) - try something like this:
var checkUserName = function (userName, email, res){
User.findOne({ name : userName }, function (err, userFromDb) {
if (err) {
console.log("there was an error: " + err;
return res.send("err: " + err.message);
}
if(userFromDb) {
res.send("duplicate");
} else {
checkEmail(email);
}
});
}

Node Express Trouble returning object to view from query

I'm trying to:
Pass user's ID to a model query, that should return the user record from mongo.
Render this user object to my view so I can use its fields.
I'm not quite sure what's going wrong - the query function finds the correct user and I can console.dir to see all the fields. When I try to return it to my view with res.render I get nothing:
Here's my route:
app.get('/account', function(req, res) {
res.render('account', {title: 'Your Account', username: req.user.name, user:account.check(req.user.id) });
});
And my query function:
exports.check = function(userId) {
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
if(err) throw err;
var collection = db.collection('test');
collection.findOne({userId : userId}, function(err, user) {
if (err) throw err;
console.log("account.check logging found user to console: ");
console.dir(user);
return user;
});
});
}
Again, this shows the proper entry
Finally my view:
<h1>Account Page</h1>
<hr>
<p>Why, Hello, there <b> {{username}} </b> </p><br/>
<p>You came from {{user.provider}}</p>
<p>{{user.lastConnected}}</p>
Go Home ~ Log Out
Any held would be most appreciated!
The MongoDB findOne function is asynchronous (it takes a callback as an argument). This means that your check function also needs to be asynchronous and take a callback as an argument (or return a promise).
Then you should call res.render() inside the callback you pass to query on success.
app.get('/account', function(req, res) {
account.check(req.user.id, function(error, user) {
if (error) {
// do something smart like res.status(500).end()
return;
}
res.render('account', {title: 'Your Account', username: req.user.name, user:user });
}
});
And the check function should be something like:
exports.check = function(userId, callback) {
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
if(err) {
callback(err);
}
var collection = db.collection('test');
collection.findOne({userId : userId}, function(err, user) {
if(err) {
callback(err);
}
console.log("account.check logging found user to console: ");
console.dir(user);
callback(null, user);
});
});
}
Of course if you don't need to do any additional processing, you can just pass your the callback argument as the callback to collection.findOne(). I just kept it this way because it was closer to what you were doing initially.

sails.js + passport.js : managing sessions

I am trying to implement a facebook connection in sails using passport. Therefore, I've created a passport.js file in my services folder, the code is given below. It looks like the login is done successfully, however the user serialization doesn't seem to work as the console.log that I put in it never appears in the console and I cannot access the user id trhough req.user once the user is supposed to be logged in. Did anyone managed to get passport working with sails?
var passport = require('passport')
, FacebookStrategy = require('passport-facebook').Strategy,
bcrypt = require('bcrypt');
// helper functions
function findById(id, fn) {
User.findOne(id).done( function(err, user){
if (err){
return fn(null, null);
}else{
return fn(null, user);
}
});
}
function findByUsername(u, fn) {
User.findOne({
username: u
}).done(function(err, user) {
// Error handling
if (err) {
return fn(null, null);
// The User was found successfully!
}else{
return fn(null, user);
}
});
}
// Passport session setup.
// To support persistent login sessions, Passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing.
passport.serializeUser(function(user, done) {
console.log("utilisateur serilizé!");
done(null, user.uid);
});
passport.deserializeUser(function(id, done) {
//console.log("coucou");
findById(id, function (err, user) {
done(err, user);
});
});
// Use the LocalStrategy within Passport.
// Strategies in passport require a `verify` function, which accept
// credentials (in this case, a username and password), and invoke a callback
// with a user object.
// using https://gist.github.com/theangryangel/5060446
// as an example
passport.use(new FacebookStrategy({
clientID: 'XXX',
clientSecret: 'XXX',
callbackURL: "http://localhost:1337/callback"
},
function(accessToken, refreshToken, profile, done) {
User.findOne({uid: profile.id}, function(err, user) {
if (err) { return done(err); }
if (user) {
//console.log('momo');
User.update({uid : user.uid},{token : accessToken},function(){done(null, user);});
} else {
console.log(profile);
var user_data = {
token : accessToken
, provider: profile.provider
, alias: profile.username
, uid: profile.id
, created: new Date().getTime()
, name: {
first: profile.name.givenName
, last: profile.name.familyName
}
, alerts: {
email: true
, mobile: false
, features: true
}
};
console.log(user_data);
User.create(user_data).done(function(err, user) {
console.log(err);
if(err) { console.log("err");throw err; }
done(null, user);
});
}
});
}
));
While I do not have a direct answer for you, this was extremely useful to when getting it to work with GitHub OAuth: https://github.com/stefanbuck/sails-social-auth-example/blob/master/config/middleware.js
This is an entire, recent, Sails.js application implementing passport so it might be of use to you to side-by-side the two in the debugger and find out what is going on.
Check out this easy and full implementation for sails.js with passport.js supporting both Email, Twitter and Facebook.
https://github.com/bmustata/sails-auth-super-template