Browsing:

Month: December 2013

Nodejs and the MEAN stack for the .NET developer part 5 – adding auth with passport-local-mongoose

I spent a whole evening figuring out authentication. I also started refactoring my code.

  • I’ve renamed /server/app.js to server.js to distuinguish from the app.js file in the /public/javascripts folder.
  • I’ve renamed the folder ‘javascripts’ to ‘js’
  • I’ve refactored the api.js and now use ‘module.exports’

What does the application need?

I decided to start simple and implement local authentication against MongoDb.
Authentication in Nodejs is handled by the middleware (Express, but it originates from Connect).
There is a fantastic module that handles authentication for you, it’s called Passport.js. Authenticating requests is as simple as calling passport.authenticate() and specifying which strategy to employ (in our case it will be LocalStrategy).

Passport-local-mongoose

Then there is passport-local-mongoose. It adds a Mongoose flavour over Passport, like class inheritance.
It adds extra properties (username and password) to your schema, although you can change ‘username’ to ’email’. It also adds a hash and salt field to store the username, the hashed password and the salt value.

Learn to Read the Source, Luke

I studied the login example back and forth and I actually think I’m grasping it now. The source code never lies. It *is* better than documentation.

Install it like so:

npm-install passport-local passport passport passport-local

Next, rewrite the schema:

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


var memberSchema = new Schema({
  nickname : String,
  email: String,
  firstName: String,
  lastName: String,
//  password: String,
  education: [{ title: String, institute: String, certification: Boolean}]
});

memberSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model('Member', memberSchema);

As you see I commented out the password attribute, as it is automatically added through passport-local-mongoose.

This is the new server.js:

var express = require('express');
var http = require('http');
var path = require('path');

var mongoose = require('mongoose');


//!!! added for passport
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var Member = require('./models/Member');


var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.use(express.favicon());
app.use(express.json());
app.use(express.urlencoded());
app.use(express.logger());
app.use(express.methodOverride());
app.use(express.cookieParser());

//!!! added for passport
app.use(express.session({ secret: 'keyboard cat' }));
app.use(passport.initialize());
app.use(passport.session());

app.use(app.router);
app.use(express.static(path.join(__dirname, '../public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

//!!! added for passport
passport.use(new LocalStrategy(Member.authenticate()));
passport.serializeUser(Member.serializeUser());
passport.deserializeUser(Member.deserializeUser());


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


//!!! moved the routes to separate file
var api = require('./routes/api')(app);

app.all('/', function(req, res) {
  res.sendfile('index.html', { root: "../public" });
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

I moved the routes to a separate file. The new routes.api looks like this:

var passport = require('passport');
var mongoose = require('mongoose');
var Member = require('../models/Member');

module.exports = function (app) {

//login section
    app.post('/login', passport.authenticate('local'), function(req, res) {
          if(req.user) {    
          res.send(req.user._id);
      }
    });


    app.post('/register', function (req, res) {
      Member.register(new Member({ username : req.body.username }), req.body.password, function(err, member) {
        if (err) {
          return res.send(err);
        }
        res.send(member);       
      });
    });


  //member section
  // /members GET
     app.get('/members',passport.authenticate('local'), function(req,res) {
    Member.find({}, function(err, data) {
      res.send(data);
    });
  });

// /member/id GET
  app.get('/member/:id',passport.authenticate('local'), function(req, res) {
    Member.findOne({ _id : req.params.id }, function(err, data) {
      res.send(data);
    });
  });


 app.put('/member/:id', passport.authenticate('local'), function(req, res) {
    delete req.body._id;
    Member.update({_id: req.params.id}, req.body, function(err, affected) {
      res.send(err);
    });
  });

  app.post('/member',passport.authenticate('local'),function(req,res) {
Member.create(req.body, function(err, member) {
      res.send(member);
    });

  });
}

The biggest gotcha
The login action returns the Mongo ID of the user. Passports saves the user details in req.user.
The id is then returned like so: res.send(req.user._id);

Register a user

auth1

After registering successfully, it is time to log on:

Log on

auth2

In return you get the ID of the logged in user.


Nodejs and the MEAN stack for the .NET developer part 4

This is part 4 of my exploration of the MEAN stack. You can find part 3 here.

This is the outline of the app we are going to create:

sketch

We need at least 5 pages to start with:

  • index.html (this will be our layout master
  • welcome.html
  • admin.html
  • signup.html
  • member.html

Routing

To be able to use routing in Angular, which we’ll need for a Single Page App (SPA), you need to install angular-route.

bower install angular-route

Step 0: create the layout master

Grab a Boostrap theme and copy the source to /public/index.html
Delete everything from line 68 until somewhere around 373.
Now you have an emtpy container div.
Add the ng-view directive into the empty container div. This is the same as @RenderBody in Razor.

<div class="container theme-showcase">
    <ng-view></ng-view> 
</div> <!-- /container -->

Now we’ll add some routing functionality in app.js.

Step 1: declare the Angular module and inject ngRoute:

var rap = angular.module('reMember-App', ['ngRoute']);

Step 2: add the routing configuration with $routeProvider in app.js

The code is self explanatory, I think.
When browsing to the root (‘/’), a page welcome.html is inserted to the layout master (index.html).
The controller that is used is the WelcomeController and so on:

var rap = angular.module('reMember-App', ['ngRoute']);

rap.config(function ($routeProvider) {

    $routeProvider.when('/',
        {
            templateUrl: 'partials/welcome.html',
            controller: 'WelcomeController'
        }).

		when('/admin',
        {
            templateUrl: 'partials/admin.html',
            controller: 'AdminController'
        }).

		when('/member',
        {
            templateUrl: 'partials/member.html',
            controller: 'MemberController'
        }).

		when('/logon',
        {
            templateUrl: 'partials/logon.html',
            controller: 'LogonController'
        }).

        otherwise( { redirecTo: '/'})

});

step 3: create a folder partials and create the 4 html pages

Here is the welcome.html:

<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
  <h1>Hello, member of the {{clubname}} !</h1>
  <p>Glad to have you with us as a member of the awesome {{clubname}}.<br>
  Please sign in to edit your personal details, or sign up as a new member!</p>

  <form class="form-inline spacer" role="form">
    <div class="form-group">
      <label class="sr-only" for="exampleInputEmail2">Email address</label>
      <input type="email" class="form-control" id="exampleInputEmail2" placeholder="Enter email">
    </div>
    <div class="form-group">
      <label class="sr-only" for="exampleInputPassword2">Password</label>
      <input type="password" class="form-control" id="exampleInputPassword2" placeholder="Password">
    </div>
    <div class="checkbox">
      <label>
        <input type="checkbox"> Remember me
      </label>
    </div>
    <button type="submit" class="btn btn-default">Sign in</button>
  </form>

  <p class="spacer">Not a member yet?</p>
  <p><a href="#/logon" class="btn btn-success" role="button">Sign up! &raquo;</a></p>
</div>

step 4: add the controllers in app.js:

rap.controller('NavController', function ($scope,$http) {
     $scope.title = "MEAN Member Application";

});

 
rap.controller('WelcomeController', function ($scope,$http) {
        $scope.clubname = "Knitting Association";
});

rap.controller('AdminController', function ($scope,$http) {
    
    // $http.get('http://localhost:3000/members').success(function(data) { $scope.members = data; });
});

rap.controller('MemberController', function ($scope,$http) {
    
    
});

rap.controller('LogonController', function ($scope,$http) {
     
    
})

step 5: the app to the index.html

This is the complete index.html:

<!DOCTYPE html>
<html lang="en" ng-app="reMember-App">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <meta name="author" content="">
  <!--  <link rel="shortcut icon" href="../../docs-assets/ico/favicon.png"> -->

    <title>Members</title>

    <!-- Bootstrap core CSS -->
    <link href="./javascripts/vendor/bootstrap/dist/css/bootstrap.css" rel="stylesheet">
    <!-- Bootstrap theme -->
    <link href="./javascripts/vendor/bootstrap/dist/css/bootstrap-theme.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="css/theme.css" rel="stylesheet">

    <!-- Just for debugging purposes. Don't actually copy this line! -->
    <!--[if lt IE 9]><script src="../../docs-assets/js/ie8-responsive-file-warning.js"></script><![endif]-->

    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
      <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
    <![endif]-->
  </head>

  <body>

    <!-- Fixed navbar -->
    <div class="navbar navbar-inverse navbar-fixed-top" role="navigation" ng-controller="NavController">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">{{title}}</a>
        </div>
        <div class="navbar-collapse collapse">
          <ul class="nav navbar-nav">
            <li><a href="#">Home</a></li>
            <li><a href="#admin">Admin</a></li>
            <li><a href="#member">Member</a></li>
            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
              <ul class="dropdown-menu">
                <li><a href="#">Action</a></li>
                <li><a href="#">Another action</a></li>
                <li><a href="#">Something else here</a></li>
                <li class="divider"></li>
                <li class="dropdown-header">Nav header</li>
                <li><a href="#">Separated link</a></li>
                <li><a href="#">One more separated link</a></li>
              </ul>
            </li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </div>

    <div class="container theme-showcase">

    <ng-view></ng-view> 


    </div> <!-- /container -->


    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="../javascripts/holder.js"></script>
    <script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script src="./javascripts/vendor/bootstrap/dist/js/bootstrap.min.js"></script>
    <script src="./javascripts/vendor/angular/angular.min.js"></script>      
    <script src="./javascripts/vendor/angular-route/angular-route.js"></script>                                    
    <script src="./javascripts/app.js"></script>      
  </body>
</html>

The result is..

hello-member

Again it seems I’m able to replace .NET for JavaScript.
This is good because now I can code on cheap and old laptops, since I do not need to install Visual Studio in it. 🙂


Nodejs and the MEAN stack for the .NET developer part 3

In this series I’m exploring the MEAN stack. In the previous posts I’ve covered the M (Mongo), the E (Express) and the N (Nodejs).
It’s time for the A. I’m going to add Angularjs and start with the frontend for the reMember application.

NPM for the frontend: Bower

Bower is a package manager for the web. It can be used to add frontend scripts to a website, like Ember, Angular, jQuery and Twitter Bootstrap.

Install Bower globally:

npm install - g bower

First, you need to tell Bower where to download its files.

touch server/.bowerrc
vim server/.bowerrc
{ "directory"  : "../public/javascripts/vendor" }

This configuration file will tell Bower to install tools into the “../public/javascripts/vendor” directory.

bower install angular bootstrap

This is the result:

apps/reMember/public/                                                                                                                   
▾ images/                                                                                                                                         
▾ javascripts/                                                                                                                                    
  ▾ vendor/                                                                                                                                       
    ▸ angular/                                                                                                                                    
    ▸ bootstrap/                                                                                                                                  
    ▸ jquery/                                                                                                                                     
▾ stylesheets/                                                                                                                                    
    style.css                                                                                                                                     
  index.html    

Hook up Angular

We did this before!

Open index.html and make it look like so:



  
        reMember
      
      
        
        
        
     

{{title}}

Create /public/javascripts/app.js:

var reMemberApp = angular.module('reMemberApp',[]);
 
reMemberApp.controller('WelcomeController', function ($scope) {
     $scope.title = "The cat just made a strange noise";
     $scope.story = "We better check her out and see if she's ok."
});

Now go ahead and browse to http://localhost:3000:

cat-plain

Add some Twitter Bootstrap styling

I grabbed this theme and copied/pasted the source into index2.html.
The I adjusted all the paths to reflect the folder structure of the reMember app.

cat-plain-twitter

Consuming the API

Add the following to /public/javascripts/app.js:

$http.get('http://localhost:3000/members').success(function(data) { $scope.members = data; });

This is the result:

var reMemberApp = angular.module('reMemberApp',[]);
 
reMemberApp.controller('WelcomeController', function ($scope,$http) {
     $scope.title = "The cat just made a strange noise";
     $scope.story = "We better check her out and see if she's ok."

     $http.get('http://localhost:3000/members').success(function(data) { $scope.members = data; });
});

And add the following html to either index.html or index2.html:

  
  • {{member.firstName}}
  • And there you go:

    cat-twitter-rest

    I’m surprised of the simplicity of all this.
    Mind you, we’ve created a minimal web app with the MEAN stack. These tools are all free and open source. Even the OS and the IDE I’m working with is free and open source.
    This is why I want to share code with the world.

    Sources:
    http://thecodebarbarian.wordpress.com/2013/07/22/introduction-to-the-mean-stack-part-one-setting-up-your-tools/


    Nodejs and the MEAN stack for the .NET developer part 2

    In the previous article we’ve set up the web application skeleton with Express for the reMember application and we wrote a first test to see if we can actually save an object to the database with Mongoose.

    In an Express generated app, ‘app.js’ is the starting point of the application. (Like Global.asax or WebApiConfig in an ASP.NET MVC app).

    Since the goal of this article is to write an api, we can clean it up a little.

    • We will not be using jade at this time, so we can clean out references to the view.
    • We can also clean out the ‘user’ lines because we are not going to use these.
    • We will comment out the routes as well and create a new default route to an index.html file
    var express = require('express');
    
    //!!don't need this:
    //var routes = require('./routes');
    //var user = require('./routes/user');
    var http = require('http');
    var path = require('path');
    
    var app = express();
    
    // all environments
    app.set('port', process.env.PORT || 3000);
    
    //!!don't need this, we're going to serve plain html:
    //app.set('views', path.join(__dirname, 'views'));
    //app.set('view engine', 'jade');
    app.use(express.favicon());
    app.use(express.logger('dev'));
    app.use(express.json());
    app.use(express.urlencoded());
    app.use(express.methodOverride());
    app.use(app.router);
    
    //!!change this as well to reflect our new folderstructure:
    app.use(express.static(path.join(__dirname, '../public')));
    
    // development only
    if ('development' == app.get('env')) {
      app.use(express.errorHandler());
    }
    
    //!!don't need this (yet)
    //app.get('/', routes.index);
    //app.get('/users', user.list);
    
    //!!add a default route
    app.all('/', function(req, res) {
      res.sendfile('index.html', { root: "../public" });
    });
    
    http.createServer(app).listen(app.get('port'), function(){
      console.log('Express server listening on port ' + app.get('port'));
    });
    

    Now create an index.html file in /public:

    <html>
    <head>
    <title>Still empty</title>
    </head>
    <body>
    <h1>Still empty..</h1>
    <p>But we're getting there..</p>
    </body>
    </html>
    

    And start up the server with node app.js
    You should now be able to browse to localhost:3000 and see the index.html.

    Debugging

    But what if you don’t and you see something like this:

    /home/jacqueline/apps/reMember/server/app.js:37
    });
    ^
    SyntaxError: Unexpected token }
        at Module._compile (module.js:439:25)
        at Object.Module._extensions..js (module.js:474:10)
        at Module.load (module.js:356:32)
        at Function.Module._load (module.js:312:12)
        at Function.Module.runMain (module.js:497:10)
        at startup (node.js:119:16)
        at node.js:902:3
    jacqueline@linuxlab:~/apps/reMember/server$ 
    

    Then you probably forgot to close a curly brace or a quote. Stop node (ctrl+c), correct the changes and start again.
    But wait, there’s an easier method.
    With nodemon it is possible to debug changes on the fly.
    Install it globally with npm install -g nodemon.

    Now start app.js with nodemon app.js

    Everytime you change and save a file the node server is automatically restarted. It crashed when something is from and it starts running as soon as you correct your mistakes:

    nodemon

    Take a look at http://localhost:3000 now:

    stillempty

    So that works.

    Are we going to write that API or what?

    Yes we are.
    Delete all the files in the routes folder.
    Create new file called api.js

    
    //!!the C# equivalent would be: 
    //using mongoose; 
    //using member;
    
    var mongoose = require('mongoose');
    var Member = require('../models/Member');
    
    
    //!! /members GET  (in ASP.NET MVC: public IEnumerable Get())
    
    exports.members = function(req,res) {
      Member.find({}, function(err, data) {
          res.send(data);
        });
    };
    

    I’ve written the C#/.NET equivalents in the comments for convenience.

    The Mongoose ‘find’ method signature is written in their API. For example:

    // executes immediately, passing results to callback
    MyModel.find({}, function (err, docs) {});
    

    The result of the query will be put in ‘docs’, which is always the 2nd parameter.

    The Mongoose API docs are a very good read and helped me enormously to understand how it works.

    Mapping the mongoose functions to a route in app.js

    We now need to map the exports.members function to the route /members.
    This happens in app.js.

    var express = require('express');
    var http = require('http');
    var path = require('path');
    
    //!!add the Mongoose module:
    var mongoose = require('mongoose');
    
    var Member = require('./models/Member');
    
    //!!add the path to the api.js file:
    var api = require('./routes/api');
    
    var app = express();
    
    // all environments
    app.set('port', process.env.PORT || 3000);
    app.use(express.favicon());
    app.use(express.logger('dev'));
    app.use(express.json());
    app.use(express.urlencoded());
    app.use(express.methodOverride());
    app.use(app.router);
    app.use(express.static(path.join(__dirname, '../public')));
    
    // development only
    if ('development' == app.get('env')) {
      app.use(express.errorHandler());
    }
    
    //!!connect to mongo:
    mongoose.connect('mongodb://localhost:27017/local');
    
    //!! map the /members route to the api.members function:
    
    app.get('/members', api.members);
    
    //default route
    app.all('/', function(req, res) {
      res.sendfile('index.html', { root: "../public" });
    });
    
    http.createServer(app).listen(app.get('port'), function(){
      console.log('Express server listening on port ' + app.get('port'));
    });
    

    Restart node (or don’t of you’re running nodemon) and browse to http://localhost:3000/members.

    grimm

    I’ve added some Grimm characters.

    Tip: use Postman to test the API.

    The github repo for reMember is here.

    Next time we’ll start building the frontend with Angularjs. (The ‘A’ in the MEAN stack).


    Nodejs and the MEAN stack for the .NET developer part 1

    Let’s have some fun with Nodejs.

    Personally I enjoy coding a lot in Vim, even more than in Visual Studio or Webstorm. Why, you might ask. Well, because Vim is extremely lightweight and totally configurable.

    Also, I like working on a Linux box, because working from the command line is a huge productivity boost. It takes some time to get used to though.

    I blogged about my Linux setup on my other blog. I also spent some time getting to know Nodejs here.

    Let’s create a Member Administration Tool (reMember) with Node, Express and Mongo

    To follow the tutorial, you need to have Node and NPM (Node Package Manager, best comparable with Nuget) installed.

    Guidelines are here.
    With Node and NPM installed, you also may want to install Mongodb.

    Functional requirements for the reMember
    The Member Admin tool contains Members for a club or whatever. You can give the members a login, so that they can update their own information. You, as an admin, get to see all the member info, while the members only can see their own nformation.

    Designing the API

    /members/1
    [table]
    Method,Result
    GET,show member with id 1
    PUT,if exists update member
    DELETE,remove member
    POST,will not work
    [/table]

    /members
    [table]
    Method,Result
    GET,lists all members
    PUT,bulk update members
    DELETE,deletes all members
    POST,creates new members
    [/table]

    Let’s go ahead and create this API.

    npm -g install express
    express reMember
    //some feedback is displayed
    cd reMember
    

    What happened?
    Express is a web application framework for Node, a bit like ASP.NET MVC or Nancy in .NET. (Or Sinatra for the Ruby folks). We need to install that on top of Node, with NPM. We add the -g switch because we want to install it globally.

    With Express it is easy to create a web application skeleton. After executing ‘express reMember’ a directory is created like this:

    ▾ public/
      ▸ images/
      ▸ javascripts/
      ▸ stylesheets/
    ▾ routes/
        index.js
        user.js
    ▾ views/                                                                                                                
        index.jade
        layout.jade
      app.js
      package.json
    

    Jade is a bit like Razor and a very elegant markup language. However, I just want to code an API and am not interested in rendering views at this time. So I’m going to delete the views folder.
    I also want the server in a separate folder, for seperation of concerns.

    This is the result:

    /home/jacqueline/apps/reMember/                                                                                      
    ▾ public/
      ▾ images/
      ▾ javascripts/
      ▾ stylesheets/
          style.css
    ▾ server/
      ▸ routes/
        app.js
        package.json
    

    Now let’s open up package.json and remove the jade dependency.
    We’ll add Mongoose, a very *very* nice ORM for Mongo.

    {
      "name": "reMember",
      "version": "0.0.1",
      "private": true,
      "scripts": {
        "start": "node app.js"
      },
      "dependencies": {
        "express": "3.4.7",
      "mongoose": "*"
      }
    }
    

    Now cd into the server folder and execute npm install
    This will install the dependencies (Express and Mongoose).

    The result is:

    /home/jacqueline/apps/reMember/
    ▾ public/                      
      ▸ images/                    
      ▸ javascripts/               
      ▸ stylesheets/               
    ▾ server/
      ▾ node_modules/
        ▸ .bin/
        ▸ express/
        ▸ mongoose/
      ▾ routes/                                                                                                             
          index.js
          user.js
        app.js
        package.json
    

    Create the model

    Create a folder ‘models’ in the server dir and name it Member.js.

    var mongoose = require('mongoose');
    
    var Schema = mongoose.Schema;
    var memberSchema = new Schema({
      nickname : String,
      email: String,
      firstName: String,
      lastName: String,
      password: String,
      education: [{ title: String, institute: String, certification: Boolean}]
    });is 
    
    module.exports = mongoose.model('Member', memberSchema);
    

    Now, if you ‘require’ this file in e.g. app.js, you can use all the methods of Member.
    Very much like ‘using’ in .NET.

    Let’s test this already!

    First install Mocha to test this. Install Mocha globally by running npm install -g mocha
    Then add the Should package in the package.json:

    {
      "name": "reMember",
      "version": "0.0.1",
      "private": true,
      "scripts": {
        "start": "node app.js"
      },
      "dependencies": {
        "express": "3.4.7",
        "mongoose": "*",
        "should" : "*"
      }
    }
    

    Run npm install.

    Next create a tests folder in the server dir.
    Create a file named 0-connection.js (that’s my own convention).

    var should = require('should');
    var Member = require('../models/Member');
    var mongoose = require('mongoose');
    
    mongoose.connect('mongodb://localhost:27017/local');
    
    describe('Member', function(){
    
        beforeEach(function(done){
            //clean the database:
            Member.remove(done);
        });
    
        describe('#save()', function() {
            it('should save', function(done) {
                var member = new Member({firstName: 'Florian' })
                member.save(function(err) {
                    if (err) return done(err);
                    //assert.equal(volunteer.firstname,'Joe');
                    member.should.have.property('firstName','Florian');
                    done();
                });
            });
        });
    });
    

    Run mocha 0-connection.js

    $:~/apps/reMember/server$ mocha tests/0-connection.js 
    
      ․
    
      1 passing (20ms)
    

    var Member = require(‘../models/Member’) this is were we import the Member class library.
    By doing that we can create an instance of a Member class like this:
    var member = new Member( {firstName: “florian” );

    Mongoose is the ‘Entity Framework’ for Mongodb. When using Mongoose to define our Member model, the Member instance automatically gets methods like save, findOne and findOneAndRemove.

    In the next post we’ll start writing the API.

    Resources:
    http://blog.mongodb.org/post/49262866911/the-mean-stack-mongodb-expressjs-angularjs-and

    http://mongoosejs.com/docs/guide.html

    http://visionmedia.github.io/mocha/#asynchronous-code