A hook (`http`) failed to load! SailsJs - sails.js

Iam learning Sails and the last days, I could implement Passport Js Authentication, but today, one error appears. It is weird, becouase I made the same steps, but now, all fails. Do I forget install some dependency?
I dont know where the error may be.
This is the error:
Express midleware for passport
error: A hook (`http`) failed to load!
error: ReferenceError: express is not defined
at Object.module.exports.http.customMiddleware (/home/tatico/estudiomate/config/passport.js:46:12)
at /home/tatico/.npm-global/lib/node_modules/sails/lib/hooks/http/initialize.js:237:33
at arrayEach (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/#sailshq/lodash/lib/index.js:1439:13)
at Function.<anonymous> (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/#sailshq/lodash/lib/index.js:3500:13)
at _afterLoadingSessionHookIfApplicable (/home/tatico/.npm-global/lib/node_modules/sails/lib/hooks/http/initialize.js:224:11)
at /home/tatico/.npm-global/lib/node_modules/sails/lib/hooks/http/initialize.js:31:18
at /home/tatico/.npm-global/lib/node_modules/sails/lib/app/private/after.js:91:14
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/async/lib/async.js:721:13
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/async/lib/async.js:52:16
at async.forEachOf.async.eachOf (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/async/lib/async.js:236:30)
at _parallel (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/async/lib/async.js:712:9)
at Object.async.parallel (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/async/lib/async.js:726:9)
at Sails.emitter.after (/home/tatico/.npm-global/lib/node_modules/sails/lib/app/private/after.js:89:11)
at _waitForSessionHookIfApplicable (/home/tatico/.npm-global/lib/node_modules/sails/lib/hooks/http/initialize.js:30:15)
at Hook.initialize (/home/tatico/.npm-global/lib/node_modules/sails/lib/hooks/http/initialize.js:42:7)
at Hook.wrapper [as initialize] (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/#sailshq/lodash/lib/index.js:3250:19)
at /home/tatico/.npm-global/lib/node_modules/sails/lib/hooks/index.js:88:16
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/async/lib/async.js:52:16
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/async/lib/async.js:548:17
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/async/lib/async.js:542:17
at _arrayEach (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/async/lib/async.js:85:13)
at Immediate.taskComplete (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/async/lib/async.js:541:13)
These are my files:
package.json:
{
"name": "estudioMate",
"private": true,
"version": "0.0.0",
"description": "a Sails application",
"keywords": [],
"dependencies": {
"bcrypt": "^1.0.2",
"ejs": "2.3.4",
"grunt": "1.0.1",
"grunt-contrib-clean": "1.0.0",
"grunt-contrib-coffee": "1.0.0",
"grunt-contrib-concat": "1.0.1",
"grunt-contrib-copy": "1.0.0",
"grunt-contrib-cssmin": "1.0.1",
"grunt-contrib-jst": "1.0.0",
"grunt-contrib-less": "1.3.0",
"grunt-contrib-uglify": "1.0.1",
"grunt-contrib-watch": "1.0.0",
"grunt-sails-linker": "~0.10.1",
"grunt-sync": "0.5.2",
"include-all": "^1.0.0",
"passport": "^0.3.2",
"passport-local": "^1.0.0",
"rc": "1.0.1",
"sails": "~0.12.11",
"sails-disk": "~0.10.9"
},
"scripts": {
"debug": "node debug app.js",
"start": "node app.js"
},
"main": "app.js",
"repository": {
"type": "git",
"url": "git://github.com/tatico/estudioMate.git"
},
"author": "tatico",
"license": ""
}
config/passport.js:
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy
bcrypt = require('bcrypt');
passport.use(new LocalStrategy(
function(email, password, done) {
User.findOne({ email: email }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
module.exports = {
providers: {
'github': {},
'facebook': {},
'twitter': {}
},
http: {
customMiddleware: function(app){
console.log('Express midleware for passport');
app.use(express.static('public'));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'keyboard cat' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(function(req,res,next){
// Set the loggedUser in locals
// to get it from the view
res.locals.loggedUser = req.user;
next();
});
}
}
};
models/User.js:
module.exports = {
attributes: {
email: {
type: 'email',
unique: true
},
admin: {
type: 'boolean',
defaultsTo: false
},
password: {
type: 'string',
required: true
},
toJSON: function() {
var obj = this.toObject();
delete obj.password;
return obj;
},
// Check a password with the saved one.
validPassword: function(password, callback) {
var obj = this.toObject();
// If there are a callback, compare async.
if (callback) {
//callback (err, res)
return bcrypt.compare(password, obj.password, callback);
}
// Otherwise, compare sync.
return bcrypt.compareSync(password, obj.password);
},
hasPassword: function(){
return !!this.password;
}
},
// Lifecycle Callbacks
beforeCreate: function(values, next) {
hashPassword(values, next);
},
beforeValidation: function(values, next) {
if( values.new_password && values.confirm_password ) {
var newPasswordMatch = values.new_password === values.confirm_password;
if( newPasswordMatch ) {
User.findOne(values.id).done(function(err, user) {
if (err) return next(err);
if( !values.password || user.validPassword(values.password) ){
// If old password is valid.
// Ovewrite password with the new password.
values.password = values.new_password;
// delete new password and confirmation.
delete values.confirm_password;
delete values.new_password;
// Hash the password.
hashPassword(values, next);
}
});
}
} else if (values.id) {
// If we are updating the data but the password is not submited.
User.findOne(values.id).done(function(err, user) {
if (err) {
return next(err);
} else {
// Take the same password user had.
values.password = user.password;
next();
}
});
} else {
next();
}
},
beforeUpdate: function(values, next) {
if(values.password) hashPassword(values, next);
else next();
}
};
var bcrypt = require('bcrypt');
function hashPassword(values, next) {
bcrypt.hash(values.password, 10, function(err, hash) {
if (err) return next(err);
values.password = hash;
next();
});
};

Add var express = require('express'); at top of passport.js

Related

How do I use populate with callbacks?

User model
const Schema = mongoose.Schema
const userSchema = new Schema({
username: { type: String, required: true },
email: { type: String, reuired: true },
password: { type: String, required: true },
posts:[{ type: Schema.Types.ObjectId, ref: "Posts" }]
}, { timestamps: true })
Post model
const Schema = mongoose.Schema;
const postSchema = new Schema({
title: { type: String, required: true },
content: { type: String, required: true },
user: { type: Schema.Types.ObjectId, ref: "User" },
}, { timestamps: true }
endpoint for getting all posts with all users information
listPostsWithUsers: (req, res, next) => {
Post.find({}, (error, posts) => {
if (error) {
return res.status(500).json({ error: "something went wrong" })
} else if (!posts) {
return res.status(400).json({ msg: "sorry no posts" })
} else if (posts) {
return res.status(200).json({ posts })
}
})
}
The output should be the returned posts with the user object so that I can identify which post the user has posted.
Now, my question is how do I apply populate() method in the above endpoint. Mostly all examples are with exec() function but I've seen no example with callbacks. It's kind of a syntax problem.
Thank you.
Update#1: The result I'm getting currently.
{
"posts": [
{
"_id": "5e65cce5ebddec0c5cc925ab",
"title": "Neil's Post",
"content": "post by neil.",
"createdAt": "2020-03-09T04:58:13.900Z",
"updatedAt": "2020-03-09T04:58:13.900Z",
"__v": 0
},
{
"_id": "5e65cd32ebddec0c5cc925ad",
"title": "Slash's post",
"content": "post by slash.",
"createdAt": "2020-03-09T04:59:30.180Z",
"updatedAt": "2020-03-09T04:59:30.180Z",
"__v": 0
},
{
"_id": "5e65f430a989612916636e8d",
"title": "Jimmy's post",
"content": "post by jimmy",
"createdAt": "2020-03-09T07:45:52.664Z",
"updatedAt": "2020-03-09T07:45:52.664Z",
"__v": 0
}
]
}
Update#2
users collection.
{
"users": [
{
"posts": [],
"_id": "5e65ccbeebddec0c5cc925aa",
"username": "Neil",
"email": "neily888#gmail.com",
"password": "$2b$10$AHHRKuCX3nakMs8hdVj0DuwD5uL0/TJwkJyKZYR/TXPTrIo9f80IW",
"createdAt": "2020-03-09T04:57:35.008Z",
"updatedAt": "2020-03-09T04:57:35.008Z",
"__v": 0
},
{
"posts": [],
"_id": "5e65cd0eebddec0c5cc925ac",
"username": "Slash",
"email": "slash938#gmail.com",
"password": "$2b$10$QQX/CFJjmpGdBAEogQ4XO.1e1ZowuPCX7pJcHTUav7NfatGgp6sa6",
"createdAt": "2020-03-09T04:58:54.520Z",
"updatedAt": "2020-03-09T04:58:54.520Z",
"__v": 0
},
{
"posts": [],
"_id": "5e65f408a989612916636e8c",
"username": "Jimmy",
"email": "jimmy787#gmail.com",
"password": "$2b$10$/DjwWYIlNswgmYt3vo7hJeNupfBdFGe7p77uisYUViKv8IdhasDC.",
"createdAt": "2020-03-09T07:45:12.293Z",
"updatedAt": "2020-03-09T07:45:12.293Z",
"__v": 0
}
]
}
Update#3:
usersController
const User = require("../models/User")
module.exports = {
createUser: (req, res) => {
User.create(req.body, (err, createdUser) => {
if (err) console.log(err)
res.json({createdUser})
})
},
listUsers: (res) => {
User.find({}, (err, users) => {
if (err) console.log(err)
res.json({users})
})
},
getUser: (req, res) => {
User.findById(req.params.id, (err, user) => {
if (err) console.log(err)
return res.json({user})
})
},
updateUser: (req, res) => {
const user = {
username: req.body.username,
email: req.body.email,
password: req.body.password
}
User.findOneAndUpdate(req.params.id, user, { new: true }, (err, updatedUser) => {
if (err) console.log(err)
res.json({updatedUser})
})
},
deleteUser: (req, res) => {
User.findByIdAndDelete(req.params.id, (err, deleteduser) => {
if (err) console.log(err)
return res.status(200).json({ user: deleteduser })
})
}
}
postsController
const Post = require("../models/Post")
module.exports = {
createPost: (req, res) => {
const data = {
title: req.body.title,
description: req.body.description,
}
Post.create(data, (err, newPost) => {
if (err) console.log(err);
return res.status(200).json({ newPost })
})
},
listPosts: (res) => {
Post.find({}, async (err, posts) => {
if (err) console.log(err);
posts = await Post.populate(posts, {
path: "user",
model: "User"
})
return res.status(200).json({ posts })
})
},
findPost: (req, res) => {
Post.findById(req.params.id, (err, post) => {
if (err) console.log(err);
return res.json({ post })
}
)
},
updatePost: (req, res) => {
const post = {
title: req.body.title,
description: req.body.description
}
Post.findByIdAndUpdate(req.params.id, post, { new: true },(err, updatedPost) => {
if (err) console.log(err);
return res.status(200).json({ updatedPost })
})
},
deletePost: (req, res) => {
Post.findByIdAndDelete(req.params.id, (err, deletedPost) => {
if (err) console.log(err);
return res.status(200).json({ deletedPost })
})
}
}
Update#4
router.get("/posts/:id", usersController.getUserPosts) `
getUserPosts: (req, res) => {
User.findById(req.params.id, async (err, user) => {
if (err) {
return res.status(500).json({ error: "Server error" })
} else if (!user) {
return res.status(400).json({ error: "No user" })
} else if (user) {
user = await User.populate("user", {
path: "posts",
model: "Post"
})
return res.status(200).json({ user })
}
})
}
I suggest you to use mongoose populate.
listPostsWithUsers : (req, res, next) => {
Post.find({}).populate('user').exec(function (err, data) {
if (err) {
console.log(err);
} else {
console.log(data);
}
})
}
You can refer this official mongoose populate document
You can even populate as many fields required by using populate as
populate([{ path: 'user' }, { path: 'book', select: { author: 1 } }])
with the help of select in populate, you can project the required fields (get only those fields from populated collection.)
Edit 1
createPost: (req, res) => {
const data = {
title: req.body.title,
description: req.body.description,
user: req.user._id,
}
Post.create(data, (err, newPost) => {
if (err) console.log(err);
return res.status(200).json({ newPost })
})
You will need to add user field in post while creating.
take user id from token or from query and you would be good to go.
Edit 2
getUserPosts: (req, res) => {
User.findById(req.params.id).populate([{ path: 'posts' }])
.exec(function (err, data) {
if (err) {
console.log(err);
} else {
console.log(data);
}
});
}
You are finding data in user module and you want to populate post data, so you just need to say which field you want to populate as you have already defined on field which model to refer by adding ref with that field in mongoose schema.
getUserPosts: (req, res) => {
User.findById(req.params.id, async (err, user) => {
if (err) {
return res.status(500).json({ error: "Server error" })
} else if (!user) {
return res.status(400).json({ error: "No user" })
} else if (user) {
user = await User.populate("posts")
return res.status(200).json({ user })
}
})
}
This should also work for you.
You can do that after getting the posts as:
listPostsWithUsers: (req, res, next) => {
Post.find({}, async (error, posts) => {
if (error) {
return res.status(500).json({ error: "something went wrong" })
} else if (!posts) {
return res.status(400).json({ msg: "sorry no posts" })
} else if (posts) {
posts = await Post.populate(posts, {
path: 'user',
model: 'User'
});
return res.status(200).json({ posts })
}
})
}

"Cannot read property 'apply' of undefined"? in loopback 3

i don't know why i have this error
when i executing the method in the loopback explorer gives the error
This is the .js file used in the project
'use strict';
module.exports = function(Puntoventa) {
var app = require('../../server/server');
Puntoventa.getAll = function() {
Puntoventa.find({ where: { nombre: !null } }, function(err, punto) {
if (err) return callback(err);
return punto;
});
}
}
and this is the model .json
"name": "puntoVenta",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"acls": [],
"methods": {
"getAll": {
"accepts": [],
"returns": [{
"arg": "punto",
"type": "object",
"root": true,
}],
"http": [{
"path": "/getAll",
"verb": "get"
}]
}
}
The error is due to a bug in sql query, you cannot use !null instead you can use neq given by loopback
Puntoventa.find({ where: { nombre: { "neq": null} } }, function(err, punto) {
if (err) return callback(err);
return punto;
});
Please use { "neq": null} } and define callback in getAll().
Puntoventa.getAll = function(callback) {
Puntoventa.find({ where: { nombre: { "neq": null} } } }, function(err, punto) {
if (err) return callback(err);
return callback(null,punto);
});
}

I have an error with passport.js implementation in Sails.js

I have a problem with Sails Passport implementation. This error appears in my terminal:
/home/tatico/sinGualichoPassport/config/passport.js:19
if (!user.validPassword(password)) {
^
TypeError: user.validPassword is not a function
at /home/tatico/sinGualichoPassport/config/passport.js:19:17
at returnResults (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/lib/waterline/query/finders/basic.js:180:9)
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/lib/waterline/query/finders/basic.js:86:16
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/lib/waterline/query/finders/operations.js:83:7
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/node_modules/async/lib/async.js:52:16
at Object.async.forEachOf.async.eachOf (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/node_modules/async/lib/async.js:236:30)
at Object.async.forEach.async.each (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/node_modules/async/lib/async.js:209:22)
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/lib/waterline/query/finders/operations.js:436:11
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/lib/waterline/query/finders/operations.js:574:5
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/node_modules/async/lib/async.js:52:16
at Object.async.forEachOf.async.eachOf (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/node_modules/async/lib/async.js:236:30)
at Object.async.forEach.async.each (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/node_modules/async/lib/async.js:209:22)
at _buildChildOpts (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/lib/waterline/query/finders/operations.js:464:9)
at _execChildOpts (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/lib/waterline/query/finders/operations.js:432:8)
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/lib/waterline/query/finders/operations.js:81:10
at wrapper (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/node_modules/lodash/index.js:3592:19)
at applyInOriginalCtx (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/lib/waterline/utils/normalize.js:421:80)
at wrappedCallback (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/lib/waterline/utils/normalize.js:324:18)
at callback.success (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/node_modules/switchback/lib/normalize.js:33:31)
at _switch (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/node_modules/switchback/lib/factory.js:58:28)
at /home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/lib/waterline/adapter/dql.js:166:7
at wrapper (/home/tatico/.npm-global/lib/node_modules/sails/node_modules/waterline/node_modules/lodash/index.js:3592:19)
This is my Files:
config/passport.js:
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy
bcrypt = require('bcrypt');
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
module.exports = {
http: {
customMiddleware: function(app){
console.log('Express midleware for passport');
app.use(express.static('public'));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'keyboard cat' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(function(req,res,next){
// Set the loggedUser in locals *does it work?
// to get it from the view
res.locals.loggedUser = req.user;
next();
});
}
}
};
UserController.js
module.exports = {
auth: function(req, res) {
return res.view();
},
create: function(req, res, next) {
User.create( req.params.all(), function createdUser(err, user){
if (err) {
return res.negotiate(err);
}
req.session.authenticated = true;
req.session.user = user;
return res.json(user);
});
},
login: function(req, res, next) {
// Use Passport LocalStrategy
require('passport').authenticate('local', function(err, user, info){
if ((err) || (!user)) next(err);
req.login(user, function(err){
if (err) return res.redirect('/user/auth');
// Redirect to the user page.
return res.redirect('/user/' + user.id);
});
})(req, res);
},
logout: function(req, res){
// Call Passport method to destroy the session.
req.logout();
// Redirect to home page.
return res.redirect('/');
}
};
User.js:
module.exports = {
attributes: {
email: {
type: 'string',
required: true,
email: true,
unique: true
},
password: {
type: 'string',
required: true
},
username: {
type: 'string',
required: true,
unique: true
},
toJSON: function() {
var obj = this.toObject();
delete obj.password;
return obj;
}
},
// Lifecycle Callbacks
beforeCreate: function(values, next) {
hashPassword(values, next);
},
beforeUpdate: function(values, next) {
if(values.password) hashPassword(values, next);
else next();
}
}
var bcrypt = require('bcrypt');
function hashPassword(values, next) {
bcrypt.hash(values.password, 10, function(err, hash) {
if (err) return next(err);
values.password = hash;
next();
});
}
Im new in Sails, and I suppose this is a not good implementantion, Anyone can Help me and give a little feed back to improve my understanding of Sails and Passport? Thanks.
ValidPassword is not defined anywhere which is leading to this error.

Unable to receive email address in sailsjs from passportjs

I'm unable to get the email address from facebook when i'm making the following call...
// https://developers.facebook.com/docs/
// https://developers.facebook.com/docs/reference/login/
facebook: function(req, res) {
passport.authenticate('facebook', { scope : ['email'] }, function(err, user) {
req.logIn(user, function(err) {
if (err) {
return;
}
res.redirect('/');
return;
});
})(req, res);
},
This is how the response is handled and is basically the PassportJS docs code.
customMiddleware: function(app) {
passport.use(new FacebookStrategy({
clientID: "5xxxxxxxxxxxxx6",
clientSecret: "exxxxxxxxxxxxxxxxxxxxxxxxxxxd9",
callbackURL: "http://localhost:1337/auth/facebook/callback"
}, verifyHandler));
app.use(passport.initialize());
app.use(passport.session());
}
And here is the handler.
var passport = require('passport')
, FacebookStrategy = require('passport-facebook').Strategy;
var verifyHandler = function(token, tokenSecret, profile, done) {
process.nextTick(function() {
sails.log.info(profile);
Serviceseeker.findOne({uid: profile.id}, function(err, serviceseeker) {
if (serviceseeker) {
return done(null, serviceseeker);
}
else {
var data = {
provider: profile.provider,
uid: profile.id,
name: profile.displayName
};
if (profile.emails && profile.emails[0] && profile.emails[0].value) {
data.email = profile.emails[0].value;
}
if (profile.name && profile.name.givenName) {
data.firstName = profile.name.givenName;
}
if (profile.name && profile.name.familyName) {
data.lastName = profile.name.familyName;
}
Serviceseeker.create(data, function(err, serviceseeker) {
return done(err, serviceseeker);
});
}
});
});
};
And this is the response that I'm getting
info: info: { id: '1xxxxxxxxxxxxxx9',
username: undefined,
displayName: 'Txxxx Slxxxxn',
name:
{ familyName: undefined,
givenName: undefined,
middleName: undefined },
gender: undefined,
profileUrl: undefined,
provider: 'facebook',
_raw: '{"name":"Txxxx Slxxxxn","id":"1xxxxxxxxxxxxxx9"}',
_json: { name: 'Txxxx Slxxxxn', id: '1xxxxxxxxxxxxxx9' } }
Did you try:
passport.use(new FacebookStrategy({
clientID: 'CLIENT_ID',
clientSecret: 'CLIENT_SECRET',
callbackURL: "http://www.example.com/auth/facebook/callback"
passReqToCallback : true,
profileFields: ['id', 'emails', 'name'] //This
},

Is there a documentation or a tutorial for integrating passport.js into sails.js? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed last month.
Improve this question
Every tutorial or unfinished documentation out there doensn't work. This is why I ask here: Is there a simple tutorial, which really works, for passport and sails?
follow this steps two integrate passport with sails js
first :-
List these dependencies inside application_directory/package.json under dependencies
//application_directory/package.json
{
...
"dependencies": {
...
"passport": "~0.1.16",
"passport-local": "~0.1.6",
"bcrypt": "~0.7.6"
}
...
}
2-
To create user model run the following command:
sails generate model user
3- model user.js will look like the following
var bcrypt = require('bcrypt');
module.exports = {
attributes: {
username: {
type: 'string',
required: true,
unique: true
},
password: {
type: 'string',
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(null, user);
}
});
});
}
};
4- To create a controller in sails type the command
sails generate controller
AuthController will look like the following:
var passport = require('passport');
module.exports = {
login: function (req, res) {
res.view();
},
process: function(req, res){
passport.authenticate('local', function(err, user, info) {
if ((err) || (!user)) {
return res.send({
message: 'login failed'
});
res.send(err);
}
req.logIn(user, function(err) {
if (err) res.send(err);
return res.send({
message: 'login successful'
});
});
})(req, res);
},
logout: function (req,res){
req.logout();
res.send('logout successful');
}
};
module.exports.blueprints = {
actions: true,
rest: true,
shortcuts: true
};
5- add the following code to application_directory/config/routes.js
module.exports.routes = {
// (This would also work if you had a file at: `/views/home.ejs`)
'/': {
view: 'home/index'
},
'/login': {
controller: 'AuthController',
action: 'login'
},
'/logout': {
controller: 'AuthController',
action: 'logout'
}
......
}
6- Inside application_directory/config create a file passport.js and add the following code to that
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;
module.exports = {
express: {
customMiddleware: function(app){
console.log('Express midleware for passport');
app.use(passport.initialize());
app.use(passport.session());
}
}
};
7- Inside /api/services/ create a file passport.js and add the following code to that
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
bcrypt = require('bcrypt'); < /code>
//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.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
findById(id, function (err, user) {
done(err, user);
});
});
passport.use(new LocalStrategy(
function (username, password, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
findByUsername(username, function (err, user) {
if (err)
return done(null, err);
if (!user) {
return done(null, false, {
message: 'Unknown user ' + username
});
}
bcrypt.compare(password, user.password, function (err, res) {
if (!res)
return done(null, false, {
message: 'Invalid Password'
});
var returnUser = {
username: user.username,
createdAt: user.createdAt,
id: user.id
};
return done(null, returnUser, {
message: 'Logged In Successfully'
});
});
})
});
}
));
8- Modify the authenticated.js file present inside /api/policies/
/**
* Allow any authenticated user.
*/
module.exports = function (req, res, ok) {
// User is allowed, proceed to controller
var is_auth = req.isAuthenticated()
if (is_auth) return next();
// User is not allowed
else return res.redirect("/login");
};