testing facebook app with mocha - facebook

I'm developing a node.js app with Facebook login, I'm trying to do unit and integration tests with mocha. So in a function I have this code in order to login:
exports.loginFacebook = function (done){
request({uri:"https://graph.facebook.com//oauth/access_token?client_id={app-id}&client_secret={app-secret}&grant_type=client_credentials",
method: "GET",
timeout: reqOpts.timeout},
function(err, res, body) {
if(err){
throw err;
}
else{
uri2 = "https://graph.facebook.com/APP_ID/accounts/test-users?"+String(body);
request({uri:uri2,
method: "GET",
timeout: reqOpts.timeout},
function(err, res, body) {
if(err){
throw err;
}
else{
login_url = JSON.parse(body).data[0].login_url
console.log(login_url);
request({uri:login_url,
method: "GET",
timeout: reqOpts.timeout},
function(err, res, body) {
if(err){
throw err;
}
else{
request('http://localhost:4004/auth/facebook', reqOpts, function(err, res, body2) {
//console.log(res.statusCode)
//console.log(err)
done()
});
}
});
}
});
}
});
};
Basically I call Facebook API to get the access token, then I list my testing users and I finally I login with the first one. Problem: when I call the login_url, Facebook redirects to this webpage: http://i.imgur.com/V6NzuMi.jpg ("update your browser"), so I'm not able to do a correct login.
Any ideas how to solve this?
thanks!

Related

MongoDB, Nodejs routing order

I have the problem with my routes. They work but only the one that's in the code first. The code below allows me to get a ticket by ID but not by registration number. If I put the second route above the first one it's vice versa.
What can I do to fix this?
//Get a ticket by ID
app.get('/tickets/:_id', function(req, res){
Ticket.getTicketById(req.params._id, function(err, ticket){
if(err){
throw err;
}
res.json(ticket);
});
});
//Get a ticket by registration number
app.get('/tickets/:vehRegistration', function(req, res){
Ticket.getTicketByReg(req.params.vehRegistration, function(err, ticket){
if(err){
throw err;
}
res.json(ticket);
});
});
You have written the same API path twice. :param_name can't be used to differentiate between two different paths. Try
//Get a ticket by ID
app.get('/tickets/byid/:_id', function(req, res) {
Ticket.getTicketById(req.params._id, function(err, ticket) {
if (err) {
throw err;
}
res.json(ticket);
});
});
//Get a ticket by registration number
app.get('/tickets/byreg/:vehRegistration', function(req, res) {
Ticket.getTicketByReg(req.params.vehRegistration, function(err, ticket) {
if (err) {
throw err;
}
res.json(ticket);
});
});

node-postgresql db connection deprecated

I am using node-v8.9.1-x64. & postgresql-10.1-2. I have tried running this code but its gives an error "code deprecated" and even tried some other ways. It still comes back with new errors
app.get('/', function(req, res) {
// PG connect -code deprecated
pg.connect(connect, function(err, client, done) {
if(err) {
return console.error('error fetching client from pool', err);
}
client.query('SELECT * FROM books', function(err, result) {
if(err) {
return console.error('error running query', err);
}
res.render('index', {books: result.rows});
done();
});
});
I went through the documentation but I am not getting it. Please somebody help me.

My mongoDB api is getting a webtask.io token error

I'm learning about webtask.io and so I've coded a simple REST api (I'm not using Express.js here but maybe I should). It's a little webtask.io app that connects to an mlab MongoDB database and retrieves todos from a tasklist collection. The issue is that I'm getting this error:
{"code":404,"message":"unable to resolve jtn to webtask token","req_id":"1504385487318.83712"}"
Any idea how to fix this error? Here is a snippet of my code:
var MongoClient = require('mongodb').MongoClient;
...
module.exports =
function (ctx, req, res) {
// write the header and set the response type as a json
res.writeHead(200, { 'Content-Type': 'application/json' });
MongoClient.connect(ctx.data.MONGO_URL, function (err, db) {
if (err) {
res.writeHead(400, { 'Content-Type': 'application/json'});
res.end(JSON.stringify(ERROR_RESPONSE.CONNECT_ERROR));
} else {
switch(req.method) {
case 'GET':
db.collection('tasklist').find({}).sort({"dateAdded" : -1}).toArray(function(err, docs) {
if (err) {
res.writeHead(400, { 'Content-Type': 'application/json'});
res.end(JSON.stringify(ERROR_RESPONSE.GET_ERROR));
} else {
res.end(JSON.stringify(docs));
}
}); //toArray
break;
//post, delete, and put are in here
} //switch
} //else no error
db.close();
}); //Mongo connect
res.end();
} //export function
I decided to try using Express and now I'm able to run my little webtask.io without having to have a web token. I'm not sure why my first try required one and if I find that answer I will post it. Here is my working version:
/* express app as a webtask */
var MongoClient = require('mongodb').MongoClient;
var Express = require('express');
var wt = require('webtask-tools');
var app = Express();
var assert = require('assert');
var ObjectId = require('mongodb').ObjectId;
app.use(require('body-parser').json());
function doCRUD (crudType,req,res) {
MongoClient.connect(req.webtaskContext.secrets.MONGO_URL,function (err, db) {
if (err) {
res.send(JSON.stringify(err));
} else {
switch(crudType) {
case 'GET':
db.collection('tasklist').find({}).sort({"dateAdded" : -1}).toArray(function(err, docs) {
if (err) {
res.send(JSON.stringify(err));
} else {
res.end(JSON.stringify(docs));
}
}); //toArray
break;
case 'POST':
db.collection('tasklist').insertOne({"tasklist" : req.query.todo, "dateAdded" : new Date()}, function(err, r) {
assert.equal(null, err);
assert.equal(1, r.insertedCount);
});
break;
case 'DELETE':
db.collection('tasklist').deleteOne({_id: new ObjectId(req.query.id)},function(err){assert.equal(null,err)});
break;
case 'PUT':
//not implemented for this hack
break;
}
}
});
}
// GET
app.get('*', function (req, res) {
doCRUD('GET',req,res);
});
// POST
app.post('*', function (req, res) {
doCRUD('POST',req,res);
res.end();
});
// DELETE
app.delete('*', function (req, res) {
doCRUD('DELETE',req,res);
res.end();
});
// expose this express app as a webtask-compatible function*/
module.exports = wt.fromExpress(app);
This error appears if you do not specify a valid path.
Try this one for example :
https://wt-666ohgod666ohgod666ohgod666ohgod-0.run.webtask.io/antidisestablishmentarianism666

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.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