Add new values to Sails session - sails.js

Updating the session object with a new value is not working in sails.
showBrowsePage: function(req, res) {
// If not logged in set `me` property to `null` and pass tutorials to the view
if (!req.session.userId) {
return res.view('browse-tutorials-list', {
me: null
});
}
User.findOne(req.session.userId, function(err, user) {
if (err) {
return res.negotiate(err);
}
if (!user) {
sails.log.verbose('Session refers to a user who no longer exists- did you delete a user, then try to refresh the page with an open tab logged-in as that user?');
return res.view('homepage', {
me: null
});
}
req.session.me = "A test value";
return res.view('browse-tutorials-list', {
me: {
email: user.email,
gravatarURL: user.gravatarURL,
username: user.username,
admin: user.admin
},
showAddTutorialButton: true
});
});
},
Here in this function call, trying to add a new value to session object "req.session.me" but it is not getting saved in the session object.
The res is also getting send after setting the value but still it does not reflect.

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?

Sails inconsistent record creation

I use the following piece of code to create some records. If I provide incorrect values, say(password and passwordConfirmation does not match), then sometimes an institute record is created without a rollback and sometimes, rollback happens properly.
I would appreciate any help. Is there a better way to do this?
create: function (req, res) {
User.query("BEGIN TRANSACTION", function(result){
if(result) {
sails.log.info(result);
return res.serverError(result);
} else {
Institute.create({
name: req.param('name'),
shortName: req.param('shortName'),
phoneNumber: req.param('phoneNumber'),
subdomain: req.param('subdomain'),
managerEmail: req.param('email')
}, function(error, institute){
if(error) {
sails.log.info(error);
Institute.query("ROLLBACK", function(result) {
sails.log.info(result);
return res.badRequest(error);
});
} else {
User.create({
email: req.param('email'),
password: req.param('password'),
passwordConfirmation: req.param('passwordConfirmation'),
account: institute.id
}, function(error, user) {
if(error) {
sails.log.info(error);
Institute.query("ROLLBACK", function(result) {
sails.log.info(result);
return res.badRequest(error);
});
} else {
User.query("COMMIT", function(result){
sails.log.info(result);
return res.created(user);
});
}
});
}
});
}
});
}
You have a few of options, in no particular order.
1. Write a function that makes all the possible security checks before creation occurs, or use the beforeCreate life cycle call for your models.
For example, you could write a function verifyParams(params) that makes checks such as password comparison (and any other checks you want) for your user creation parameters before you create the institution, or you could just include these checks in your institution creation's beforeCreate method.
2. Delete if there is an error during your user creation
Delete theInstitute model instance in your error case of user creation:
...
User.create(..., function (error, user) {
if (error) {
Institute.destroy(institute.id, function instDestroyed(err) {
...
});
} else {
...
}
});
3. Create a user in your institute model's beforeCreate method.
module.exports = {
attributes: { ... },
beforeCreate: function(values, next) {
User.create(..., function (err, user) {
if (err) { return next(err) }
return next();
});
}
}
Personally, I use method #2 in my own apps.

How to set up mongo db in local and then in remote?

I have got the mongo db commands from the below link.
http://try.mongodb.org/
I have a project and I am able to run it. In the project we use mongodb, angular js, node js and express server.
I am able to create user from the login page.The users are stored in mongo db. I would like to know what are the users in the database.
Initially I did not install any mongodb. But some how, the user and password was stored in localhost. I hope my project will be having certain libraries.
But later, in order to learn mongo, i installed mongo to my PC. I started the mongo db and it is running successfully in the link
http://localhost:28017/.
MongoDB starting : pid=6300 port=27017 dbpath=\data\db\ 64-bit host=new-PC
Question 1
I would like to list out the users in the db, that is used by my project. Will installation of mongo db help me in some way? If not without starting mongo db, can i know where are the user details saved by my project?
Question 2
How can I set up mongo db in remote so that it is available in the internet?
Code
- Creating UserSchema
var UserSchema = new Schema({ name: String, email: { type: String, unique: true }, hashed_password: String, provider: String, salt: String, facebook: {}, twitter: {}, github: {}, google: {} });
mongoose.model('User', UserSchema);
- Code for creating user
var mongoose = require('mongoose'), User = mongoose.model('User'), q = require('q'), _ = require('lodash');
exports.create = function(req, res, next) { var reqUser = new User(req.body); var email = reqUser.email; if(!reqUser.email) { res.send(400, {message: 'Email is mandatory!'}); }
var message = null;
reqUser.provider = 'local';
var savePromise = q.when(User.findOne({'email': reqUser.email}).exec());
savePromise.then(function(user) {
return reqUser;
if(user == null)
{
return reqUser;
} else
{
if(reqUser.provider!=user.provider && !user.hashed_password)
{
user.password = reqUser.password;
} else {
throw new Error("User alredy exists!");
}
console.log("In Else");
console.log(user);
return user;
}
}, function(err){
console.log("In Error 1");
}
).then(function(user){
console.log("In then 2");
console.log(user);
return user.save();
}, function(err){
console.log("In error 2");
console.log(err);
}).then(function(obj){
console.log("In then 3");
console.log(obj);
}).fail(function(error){
console.log("In Fail");
console.log(error);
}).done(function(){
// console.log(user);
console.log("in done");
});
console.log("Returning 400 at the end");
user.save(function(err) {
if (err) {
console.log(err);
message = 'Unknowd error occured, please try again!';
if(err.code=11000)
{
message = 'User with this email already exist. Existing user? please login here';
User.findOne({
email: user.email
}, function(err, dbuser) {
if (err) {
return res.json(400, { message: message });
}else {
if(dbuser.provider!=user.provider)
{
console.log("In If");
console.log(dbuser);
if(!dbuser.hashed_password)
{
console.log("In another if");
dbuser.password = user.password;
dbuser.save(function(err){
if(err)
{
console.log(err);
}
return res.json(dbuser);
});
}else
{
console.log("Returning error");
return res.json(400, { message: message })
}
} else
{
return res.json(400, { message: message });
}
}
});
}
}else
{
return res.json(user);
}
//console.log("Returning success");
});
};
Thanks,
Sabarisri
To answer question #2 first,
you will need either an instance of mongoDB on your own server or get a hosted one.
See for example Database-as-a-service. There are quite a lot of possibilites, check out some other offers.
Your first question is confusing me. It would be helpful to see the code that creates a user.
Installation:
http://docs.mongodb.org/manual/tutorial/install-mongodb-on-windows/
Coding :
http://docs.mongohq.com/languages/nodejs.html
How to secure MongoDB with username and password

Call controller on afterCreate

I have the following code for my Sessions model:
module.exports = {
attributes: {
},
afterCreate: function(value,next) {
next();
}
};
And the following Sessions Controller:
module.exports = {
saveSession: function(res,req) {
console.log('in save');
}
};
I want to save a value to a user's session afterCreate
How can I call the saveSession function from my model? I tried Sessions.saveSession() but it doesn't work.
I don't think you need a session model and it's not a good idea to call a controller method directly.
I'd recommend just set req.session when you're trying to save the session and it'll be auto-saved when you respond from that controller action.
afterCreate will never have access to req unless you pass it down which I wouldn't recommend.
The pattern is something like:
{
// …
login: function (req,res) {
User.findOne({
username: req.param('username'),
password: req.param('password')
}).exec(function (err, user) {
if (err) return res.serverError(err);
if (!user) return res.view('/login');
req.session.user = user.toJSON();
return res.redirect('/dashboard');
});
}
// ...
I think that you want to save a value to a cookie or create another database record am i correct?
If so, you dont need to call a controller action from the model (not recommended), you just need to create a new record or save the value to the cookie, here are some alternatives that i see possible in your scenario.
creating another record:
// on models/YourModel
module.exports = {
attributes: {
},
afterCreate: function(newlyInsertedRecord,next) {
ModelOrResource.create({
param1: newlyInsertedRecord.attributeYouWant,
param2: value2
// and so on
}).exec(function(err, recordCreated){
if(err) return next(err);
// do somethign with recordCreated if you need to
// ...
next();
})
}
};
Saving a value to a cookie:
module.exports = {
attributes: {
},
afterCreate: function(newlyInsertedRecord, next) {
// do some other stuff not related to calling a controller action ;)
next();
}
};
This code was retrived from snippets from my own projects, so it should work on sails 0.9.x
Hope it helps!

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