Browsing:

Categorie: Beginning Node.js series

Beginning Node.js – local authentication with Passport-Local Mongoose – part 6

Disclaimer: This is a series about me, creating a web application in Node.js. The completed example is available here.

I have a deep respect for all those developers out there that write fantastic modules I can use in my projects. One little gem is passport-local-mongoose. I’ve written about it before but as you see I’m doing it again.

What is passport-local-mongoose?

You can plug-in passport-local-mongoose into your Mongoose Userschema. This decorates the User object with a set of methods. E.g.

  • authenticate
  • register
  • setPassword
  • serialize
  • deserialize

It also hashes the passwords. This saves a lot of work.

What we should work on

  • Users should be able to register
  • Users should be able to authenticate
  • Users should be able to change their password
  • Users should be able to change their e-mail address
  • There should be a ‘forgot password’ procedure
  • Users should be able to delete their accounts

This article covers only ‘register’ and ‘authenticate’. You can go ahead and clone the restaurant github repo for a full example.

To add local authentication to your app you’ll need to run:

Of course, you may add your own properties to the model:

var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    passportLocalMongoose = require('passport-local-mongoose');

var User = new Schema({
    uuid: {
        type: String,
        required: false
    },
    firstname: {
        type: String,
        required: true
    },
    active: {
        type: String,
        required: false
    }
});

var options = ({missingPasswordError: "Wrong password"});
User.plugin(passportLocalMongoose,options);

module.exports = mongoose.model('User', User)

Now let’s hook up Passport in our app.

Controller

Let’s create a user controller which contains the register, the login and the getLogin functions (to check if a user has logged in).
Create a file named controller.user.js and put it in the app folder:

var mongoose = require('mongoose');
var User = require('./model.user');

exports.register = function (req, res) {
    console.log("registering: " + req.body.firstName);
    User.register(new User({
        username: req.body.username,
        firstname: req.body.firstname
    }), req.body.password, function (err, user) {
        if (err) {
            console.log(err);
            return res.send(err);
        } else {
            res.send({
                success: true,
                user: user
            });
        }
    });
};

exports.login = function (req, res, next) {

    User.authenticate()(req.body.username, req.body.password, function (err, user, options) {
        if (err) return next(err);
        if (user === false) {
            res.send({
                message: options.message,
                success: false
            });
        } else {
            req.login(user, function (err) {
                res.send({
                    success: true,
                    user: user
                });
            });
        }
    });

};

exports.getLogin = function (req, res) {
    console.log(req.user);
    if (req.user) {

        return res.send({
            success: true,
            user: req.user
        });

    } //res.send(500, {status:500, message: 'internal error', type:'internal'}); == deprecated


    res.send({
        success: false,
        message: 'not authorized'
    });
};

What happens?
1. User.authenticate and User.register:
The User.authenticate and User.register are functions we get from passport-local-mongoose. I just took this code as an example.

2. Check if a user is logged in with ‘if(req.user)’
If a user is logged in, the req.user property is populated with the user object.
So if it exists, the user is logged in.

Routes

//mongodb
var mongoose = require('mongoose');
var User = require('./model.user');

var users = require('./controller.user');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var cookieParser = require('cookie-parser');
var session = require('express-session');


module.exports = function (app) {

    //initialize passport
    passport.use(User.createStrategy());
    // use static serialize and deserialize of model for passport session support
    passport.serializeUser(User.serializeUser());
    passport.deserializeUser(User.deserializeUser());

    //need this according to passport guide
    app.use(cookieParser());
    app.use(session({
        secret: 'the princess and the frog',
        saveUninitialized: true,
        resave: true
    }));
    app.use(passport.initialize());
    app.use(passport.session());

    //routes
    app.route('/register').post(users.register);
    app.route('/login').post(users.login);
    app.route('/login').get(users.getlogin);
   
   
};

Add this file to main.js, like so:

require('./app/routes.user')(app);

This will be your completed main.js:

var express = require('express');
var app = express();
var bodyparser = require('body-parser');
var mongoose = require('mongoose');

app.use(bodyparser.urlencoded({
  extended: true
}));

app.use(bodyparser.json());

mongoose.connect('mongodb://localhost:27017/restaurant');

require('./app/routes.food')(app);
require('./app/routes.user')(app);

app.use(express.static(__dirname + '/public'));

app.set('port', process.env.PORT || 3001);
app.listen(app.get('port'));
console.log("the server is running on http://localhost:" + app.get('port'));

Let’s try this

Install Postman or another REST API test tool.

  • Don’t forget to configure the headers: Content-Type application/json

First, let’s register a user (click POST):

Postman_passport

Second, let’s login:

Selection_012

Check the login status:

Selection_015

The end of this series

This is where this series end. I hope anyone will enjoy this and at least learns something from my struggles. I know I did!
Your feedback is more than welcome by the way.


Beginning Node.js – REST API with a Mongodb backend (refactoring) – part 4

Refactoring

This code in the entry point main.js in the former post is a bit verbose. If an application becomes more complex you don’t really want to put all your logic in one file. Best practice is to keep thing small, by making every program a proxy.

Disclaimer: my blog posts may not be best practice for everybody in every situation. The code I share however works for me and gets the job done. I strive to keep everything as simple as possibe.

Model, View, Controller

In this post we will create a Model and a Controller (no Views because this is still just a REST API without a frontend).
Finally we’ll create the routes.

The main.js file requires the routes, the routes require the controller, the controller requires the model.

Yep, that should do.

Create a model

So let’s clean out the mess. Create a new folder named ‘app’. From the main.js file we will put the ‘Food’ model into a separate file.

I will save the file as model.food.js.

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var FoodSchema = new Schema({
    name: String,
    description: String,
    price: String
});

mongoose.model('Food', FoodSchema);
module.exports = mongoose.model('Food');

‘Module.exports’ wraps everything so that later on you can “require” this module and use the “new” operator to create a new instance of the Food object type, which is done in the controller in the next paragraph.

Create a controller

I put the CRUD into a controller (per this example).
I will save the file as controller.food.js
Notice how I ‘require’ the Model in the first line.

var Food = require('./model.food.js');

exports.create = function (req, res) {
    var food = new Food(req.body);
    console.log(food);
    food.save(function (err) {
        if (err) {
            return res.send({
                message: err
            });
        } else {
            res.send({
                success: true,
                food: food
            });
        }
    });
};

exports.list = function (req, res) {
    Food.find(function (err, data) {
        if (err) {
            res.send(err);
        }
        res.json({
            success: true,
            food: data
        });
    });
};


exports.findOne = function (req, res) {
    Food.findOne({
        _id: req.params.id
    }, function (error, response) {
        if (error) {
            res.send(error);
        } else {
            res.send({
                success: true,
                food: response
            });
        }
    });
};

exports.findByName = function (req, res) {
    Food.findOne({
        name: req.params.name
    }, function (error, response) {
        if (error || !response) {
            res.status(404).send({
                status: 401,
                message: 'not found'
            });
        } else {
            res.send({
                success: true,
                food: response
            });
        }
    });
}

Here I am basically wrapping methods around the Food object, using exports.methodname.
In case you are wondering (I was, and have to admit still am wondering about this sometimes), this article explains the difference between ‘module.exports’ and ‘exports’ as follows: ‘module.exports’ is the real deal, exports is just its little helper. For now, I am OK with that. Let’s just get things done already. 🙂

Separate the routes

Here the controller.food.js file is required.
I will save the file as routes.food.js.

//mongodb
var foodstuff = require('./controller.food');

module.exports = function (app) {
    app.route('/food').post(foodstuff.create);
    app.route('/food').get(foodstuff.list);
    app.route('/food/:id').get(foodstuff.findOne);
    app.route('/foodname/:name').get(foodstuff.findByName);
};

Well then, we’re done. Now let’s give main.js a haircut.

Refactor main.js

So, we now have a small and clean main.js file.

var express = require('express');
var app = express();
var bodyparser = require('body-parser');
var mongoose = require('mongoose');

app.use(bodyparser.urlencoded({
  extended: true
}));

app.use(bodyparser.json());

mongoose.connect('mongodb://localhost:27017/restaurant');

require('./app/routes.food')(app);

app.use(express.static(__dirname + '/public'));

app.set('port', process.env.PORT || 3001);
app.listen(app.get('port'));
console.log("the server is running on http://localhost:" + app.get('port'));

If you followed along, the directory structure looks like this:

.
├── app
│   ├── controller.food.js
│   ├── model.food.js
│   └── routes.food.js
├── main.js
├── node_modules
│   ├── body-parser
│   ├── express
│   └── mongoose
├── package.json
└── public
├── index.html

What’s next?

Next up is authentication testing.


Beginning Node.js – REST API with a Mongodb backend – part 3

This is the sequel to this article. I’m building a REST API from the ground up with Node.js and Express.js 4. I’m adding functionality as I go. I’m starting with Node.js, then I’m adding Express and now I’m adding Mongoose. In the next articles I will be adding Passport.js for authentication and start building a frontend, either with Angular of Ember.

Things have changed slightly since my former series, see here. That’s because Express.js version 3 has evolved to version 4. The main difference between version 3 and 4 is that version 3 contains middleware (JSON parsers, session support and so on). In version 4 you need to add the middleware yourself. That means installing body-parser, session and so on with NPM.

In my former article we used a JSON string with data. Now let’s use a real data backend: MongoDb. Mongoose is an ORM for MongoDb for Node.js, so let’s add the module to the project:

npm install --save mongoose

We also need to install the body-parser, which parses JSON bodies for Express.

npm install --save body-parser

Next, copy all of this to your main.js file:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
//mongoose uses Schema as a layer on a MongoDb document (which represents a model):
var Schema = mongoose.Schema;

app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

//connect to mongodb:
mongoose.connect('mongodb://localhost:27017/restaurant');

//create a Schema for our food:
var FoodSchema = new Schema({
    name: {
        type: String,
        index: {
            unique: true
        }
    },
    description: String,
    price: String
});


// Use the schema to register a model with MongoDb
mongoose.model('Food', FoodSchema);
var food = mongoose.model('Food');

//POST verb
app.post('/food', function (req, res) {
    food.create(req.body, function (err, food) {
        if (err) {
            res.send(401, err);
            return;
        }
        res.send(req.body);
    });
});

//GET verb
app.get('/food', function (req, res) {
    food.find(function (err, data) {
        if (err) {
            res.send(err);
        }
        res.json(data);
    });
});

//GET/id
app.get('/food/:id', function (req, res) {
    food.findOne({
        _id: req.params.id
    }, function (error, response) {
        if (error) {
            res.send(error);
        } else {
            res.send(response);
        }
    });
});

//GET by name
app.get('/foodname/:name', function (req, res) {
    food.findOne({
        name: req.params.name
    }, function (error, response) {
        if (error || !response) {
            res.send("not on the menu");
        } else {
            res.send(response);
        }
    });
});


app.set('port', process.env.PORT || 3000);
app.listen(app.get('port'));
console.log("the server is running on http://localhost:" + app.get('port'));

Now run it with the following command:

nodemon main.js

What happened?

Let’s dissect the code from the previous paragraph:

1.
We added and instantiated the prerequisites and connected to our MongodB instance

var bodyParser = require('body-parser');
var mongoose = require('mongoose');
//mongoose uses Schema as a layer on a MongoDb document (which represents a model):
var Schema = mongoose.Schema;

app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

//connect to mongodb:
mongoose.connect('mongodb://localhost:27017/restaurant');

2.
We create a Schema for our Food class:

//create a Schema for our food:
var FoodSchema = new Schema({
    name: {
        type: String,
        index: {
            unique: true
        }
    },
    description: String,
    price: String
});

3.
Then we used the schema to register a model with MongoDb
mongoose.model('Food', FoodSchema);
var food = mongoose.model('Food');

4.
And then we are ready to define our CRUD methods, e.g.

//POST verb
app.post('/food', function (req, res) {
    food.create(req.body, function (err, food) {
        if (err) {
            res.send(401, err);
            return;
        }
        res.send(req.body);
    });
});

//GET verb
app.get('/food', function (req, res) {
    food.find(function (err, data) {
        if (err) {
            res.send(err);
        }
        res.json(data);
    });
});

Using the API with Curl

You can add a menu item with the following command:

curl -H "Content-Type: application/json" -d '{ "name": "papadums", "description" : "Thin Bread", "price" : "2.00" }' http://localhost:3000/food

Issue a get:

curl http://localhost:3000/food

Beginning Node.js – REST API with Express 4 – part 2

This is the most simple REST API possible. I will explain every single detail in this post.

var express = require('express');
var app = express();

var menu = [{"description" : "papadums", "price":"2,00"}, {"description" : "chicken tikka masala", "price":"14,00"},{"description" : "fisher king beer", "price":"2,50"},{"description" : "sag paneer", "price":"6,00"}];

app.use(express.static(__dirname + '/public'));

app.get('/food', function(req, res){
  res.send(menu);
});

app.set('port', process.env.PORT || 3000);
app.listen(app.get('port'));
console.log("the server is running on http://localhost:" + app.get('port'));

Let’s get started

First create a folder named ‘restaurant’ or whatever you would like to name the API.
Then run ‘npm init’ to create a package.json file. This file contains metadata, dependencies etc.:

mkdir restaurant
cd restaurant
npm init

You will get a bunch of questions. Answer them (or accept the defaults) and hit enter:

About to write to /Users/jacqueline/Dropbox/devel/restaurant/package.json:
{
  "name": "restaurant",
  "version": "0.1.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Jacqueline",
  "license": "MIT"
}

Is this ok? (yes)

Install Express

Next we will install Express with NPM. Express is a minimalist web framework for Node.js.

jacqueline@nsa:~/Dropbox/devel/restaurant$ npm install express --save

You will now see ‘express’ mentioned in the package.json.
The ‘–save’ parameter adds a “^” before the package, it will make sure the right version is used.

Create the app

Create a file named ‘main.js’ (that’s how I named the main file in my package.json, you can also name it app.js or server.js).

Add these contents:

var express = require('express');
var app = express();
app.get('/', function(req, res){
      res.send('hello world');
    });

 app.listen(3000);

Next install nodemon because it is awesome. It restarts node every time a file in the project is changed.
Add the ‘-g’ parameter because nodemon should be installed globally and not just as a module in the project folder.

npm install -g nodemon

Now run nodemon main.js on the commandline. It will return:

jacqueline@nsa:~/Dropbox/devel/restaurant$ nodemon main.js 
18 Oct 08:04:59 - [nodemon] v1.2.0
18 Oct 08:04:59 - [nodemon] to restart at any time, enter `rs`
18 Oct 08:04:59 - [nodemon] watching: *.*
18 Oct 08:04:59 - [nodemon] starting `node main.js`

Now browse to http://localhost:3000. This will display ‘Hello World’ in the browser.

Serve JSON data

Alter your main.js file and add some json and change the app.get bit:

var express = require('express');
var app = express();

var menu = [{"description" : "papadums", "price":"2,00"}, {"description" : "chicken tikka masala", "price":"14,00"},
{"description" : "fisher king beer", "price":"2,50"},{"description" : "sag paneer", "price":"6,00"}];

app.get('/food', function(req, res){
  res.send(menu);
});

app.listen(3000);

Now if we browse to http://localhost/food, we will retrieve our delicious menu. We can also a REST client like POSTMAN to test:
food

With curl:

curl http://localhost:3000/food
[{"description":"papadums","price":"2,00"},{"description":"chicken tikka masala","price":"14,00"},{"description":"fisher king beer","price":"2,50"},{"description":"sag paneer","price":"6,00"}]

Consuming the API

Create a folder called public in your app directory.

Next add this line to main.js, with this we’ll tell Express to go and find index.html files in a subfolder called public:

app.use(express.static(__dirname + '/public'));

Drop an index.html in the public folder.
This makes the directory structure look like so:

restaurant/
├── main.js
├── node_modules
│   └── express
├── package.json
└── public
└── index.html

Open index.html and add the following code:



  
  
  
    

Welcome to my restaurant!

On the menu:

And the result is..:

food-awesom

Add Bootstrap with Bower

Bower is like NPM, but for front end scripts. You can use NPM for frontend scripts as well, but I like to keept them separate.

npm install -g bower

Create a file named .bowerrc to tell Bower to put the javascripts into a /public/js:

vim .bowerrc
{
    "directory" : "public/js"
 }

You can create a bower.json file to organize the dependencies:

bower init

jacqueline@nsa:~/Dropbox/devel/restaurant$ bower init
? name: restaurant
? version: 0.1.0
? description: menu app
? main file: main.js
? what types of modules does this package expose?: node
? keywords:
? authors: jacqueline <jacqueline@nsa.gov>
? license: MIT

Then install your client side javascript dependencies like so:

bower install --save bootstrap

Now we can add some styling:

nicerestaurant

Last but not least: some feedback when starting the server

In Express you can define variables with app.set. I would suggest to configure the port like this:

app.set('port', process.env.PORT || 3000);
app.listen(app.get('port'));
console.log("the server is running on http://localhost:" + app.get('port'));

process.env.PORT || 3000 means: whatever is in the environment variable PORT, or use 3000 if there’s nothing there.

This makes completed main.js look like this:

var express = require('express');
var app = express();

var menu = [{"description" : "papadums", "price":"2,00"}, {"description" : "chicken tikka masala", "price":"14,00"},
{"description" : "fisher king beer", "price":"2,50"},{"description" : "sag paneer", "price":"6,00"}];

app.get('/food', function(req, res){
  res.send(menu);
});

app.use(express.static(__dirname + '/public'));

app.set('port', process.env.PORT || 3000);
app.listen(app.get('port'));
console.log("the server is running on http://localhost:" + app.get('port'));

And this is where this tutorial ends. I love open source. It’s great to be able to use all these tools (Node, NPM, Express) and be very productive. Next time I will show how to use a (NoSQL) database. Not sure to use MongoDb or Postgresql yet. We’ll see.


Beginning Node.js – callbacks – part 1

Disclaimer: This is a series about me, creating a web application in Node.js. The completed example is available here.

And from there the series end, because frontend frameworks will take over.

In this article about the MEAN stack, I’m not spending much time on Node.js. However, Node.js is quite awesome. It’s lightweight, cross platform and it runs JavaScript files. But what is it?

  • Node.js is like IIS.
  • You can use a module like Express.js (or Restify, Sails.js, Hapi etc.) to implement a RESTful API, much like the ASP.NET Web API.
  • You install modules (packages) with NPM, which is comparable to Nuget.

Node.js is a platform built on Chrome’s JavaScript runtime (v8). Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

So what does that even mean? And how to get started? Apart from this blog, there are plenty of tutorials out there and also great books. These are probably much better than this intro, however I would like to share that piece of code that made it click for me. And if I not write down my words, they are wasted.

What do we need?

  • Node.js (I’m on v0.10.30). We will use Node.js to to build server side applications. So no IIS, applications pools and .NET. All you need is the 5 MB’s of Node.js! Let’s sink that in for a moment!
  • A code editor of choice (I prefer Vim and Brackets)
  • Linux OS, Mac OS or Windows 7/8. I’m on a Mac and on Ubuntu 14.04. I only use Windows at work.
  • For Windows, you will need Python 2.7, Visual Studio Express and node-gyp installed locally. Check this. These are prerequisites to build node modules on Windows (a bit of a pain indeed)
  • Just a little bit of a coding background.

Node.js installation

Linux or Mac
To install Node.js on Linux or Mac, I would advise to follow this gist:

echo 'export PATH=$HOME/local/bin:$PATH' >> ~/.bashrc
. ~/.bashrc
mkdir ~/local
mkdir ~/node-latest-install
cd ~/node-latest-install
curl http://nodejs.org/dist/node-latest.tar.gz | tar xz --strip-components=1
./configure --prefix=~/local
make install # ok, fine, this step probably takes more than 30 seconds...
curl https://www.npmjs.org/install.sh | sh

Windows
To install Node.js on Windows just install the .msi.from the Node.js website.
For NPM don’t forget to create an NPM folder in C:\Users\Username\AppData\Roaming\npm\

The basics: callbacks

Normally, code gets executed from top to bottom:

function dothis() {
// do some IO heavy work, or get data from a file
}

function dothat() {
//doing that
}

dothis();
dothat();

If ‘dothis’ is CPU intensive, or IO intensive, it takes a long time before the code reaches ‘dothat’. In the mean time, nothing happens. The code is ‘blocking’.
In .NET you can solve blocking operations by using another thread, or write the code asynchronously.
But Node.js code is almost exclusively asynchronous. There is but ONE thread in Node.js.

So in Node, code is executed asynchronously. While some IO heavy operations occurs, Node can do other stuff. When the heavy operation is finished, the function involved ‘calls back’, like saying: ” Hey, I’m done. Here is the result”.

So how do we write asynchronous code in Node?

Consider this example where I want to display an order of Indian food on the screen.
order.txt contains a list of Indian food.

var fs = require('fs'); // this is like using System.IO

//initialize the variable
var theOrder;

//this is a function that reads the contents of order.txt. 

function orderSomething() {
   //the 'readFile' method takes (at least) 2 arguments: the file, and also a callback (result).
   fs.readFile('order.txt', function(result){
   theOrder = result;
   });
  }

console.log("The customer ordered:\n" + orderSomething());

Now save this code as test.js and run it:

jacqueline@laptop:~$ node test.js
The custumer ordered:
undefined

So this does not display my order. Why not?
Because when console.log is executed, the function orderSomething is not ready yet.

We can solve the problem by adding a parameter to the orderSomething function. In Node, the last parameter of a function is a function, that will be executed when orderSomething is finished: orderSomething(doThisWhenFinished). (In C# you can also pass a function as a parameter, with Func<> and Action<>, however I’m not sure it knows about async behavior).

So, we basically add a function to a function (which can contain another function and so on).
This is very important. The parameter of a function in JavaScript can be another function, that gets executed when the first function is done.

var theOrder;

//first, orderSomething and when it's done, execute 'done'
function orderSomething(done) {
  fs.readFile('order.txt', function(err,result) {
    if (err) { throw err; }
    theOrder = result;
// call this when done:
    done();
  });
}

function showOrder(){
 console.log("The customer ordered:\n" + theOrder);
}

orderSomething(showOrder);

Now run this code:

jacqueline@laptop:~$ node test.js
The custumer ordered:
//Chicken Tikka Massala
//Papadums
//King Fisher Beer

This is how Node.js works. The last argument of a function is the callback, which gets executed when the function is ready.

Wrapping up

We can rewrite the above example as follows:

var fs = require("fs");
fs.readFile("order.txt","utf-8", function (error, result) {
     console.log(result);
  });

Read the file, then display the result.

That was all.