Sunday, September 20, 2015

Creating an application with SailsJS and OrientDB on your Mac

Pre-Conditions

This article has been created for:

  • SailsJS 0.11.0
  • sails-orientdb 0.10.55
  • OrientDB 2.0.12

This article will not be updated!

Pre-requisites

  • Homebrew installed on Mac
  • OrientDB installed on Mac
  • A database called "testdb" and a user "apple" with password "test" and "admin" role

Part 1: Install and test sails

Install NodeJS

brew install node

Install SailsJS

sudo npm -g install sails

If you receive an error such as "sh: node: command not found" then try without the "sudo" command

Create new Sails application

sails new testProject

Change in to the testProject directory:

cd testProject

Create first API

sails generate api profile

Test the setup

Start sails.

sails lift

During start you'll be told that you don't have a project wide migrate setting configured yet. Choose "2" which means that the db will be altered if there are any changes.

1. safe  - never auto-migrate my database(s). I will do it myself (by hand) 
 2. alter - auto-migrate, but attempt to keep my existing data (experimental)
 3. drop  - wipe/drop ALL my data and rebuild models every time I lift Sails

What would you like Sails to do?

info: To skip this prompt in the future, set `sails.config.models.migrate`.
info: (conventionally, this is done in `config/models.js`)

warn: ** DO NOT CHOOSE "2" or "3" IF YOU ARE WORKING WITH PRODUCTION DATA **

prompt: ?:  2

Once sails has started try to reach the main page. You should see the main index page.

http://localhost:1337/

Then connect to the profile list page. You should see brackets as no data has been added yet "[]".

http://localhost:1337/profile

Try to add some data

http://localhost:1337/profile/create?age=22&haircolor=Brown
http://localhost:1337/profile/create?age=40&haircolor=Black

Go back to the profile list page and now you should see both entries in the output of the web page. Sails is using a local disk db by default.

http://localhost:1337/profile

Output in webpage

[
  {
    "age": "22",
    "haircolor": "Brown",
    "createdAt": "2015-07-17T17:00:10.403Z",
    "updatedAt": "2015-07-17T17:00:10.403Z",
    "id": 1
  },
  {
    "age": "40",
    "haircolor": "Black",
    "createdAt": "2015-07-17T17:01:02.251Z",
    "updatedAt": "2015-07-17T17:01:02.251Z",
    "id": 2
  }
]

Part 2: Adding the OrientDb Adapter

Please make sure that you have a database called "testdb" in OrientDB and added a user called "apple" with password "test" and the "admin" role.

Install the adapter

npm install sails-orientdb --save

Configure Sails to use the OrientDB Adapter

Configure config/connections.js

Add the orientDbServer1 related configuration in to connections.js and don't forget to add an additional comma after the already existing somePostgresqlServer configuration entry.

  /***************************************************************************
  *                                                                          *
  * PostgreSQL is another officially supported relational database.          *
  * http://en.wikipedia.org/wiki/PostgreSQL                                  *
  *                                                                          *
  * Run: npm install sails-postgresql                                        *
  *                                                                          *
  *                                                                          *
  ***************************************************************************/
  somePostgresqlServer: {
    adapter: 'sails-postgresql',
    host: 'YOUR_POSTGRES_SERVER_HOSTNAME_OR_IP_ADDRESS',
    user: 'YOUR_POSTGRES_USER',
    password: 'YOUR_POSTGRES_PASSWORD',
    database: 'YOUR_POSTGRES_DB'
  },


  /***************************************************************************
  *                                                                          *
  * More adapters: https://github.com/balderdashy/sails                      *
  *                                                                          *
  ***************************************************************************/
  orientDbServer1: {
   adapter: 'sails-orientdb',
   host: 'localhost',
   port: 2424, 
   database: 'testdb',
   options: {
     databaseType: 'graph',
     databaseUser: 'apple',
     databasePassword: 'test'
   }
 }

Configure config/models.js

Uncomment the connection and the migrate configuration options and change the name of the connection attribute to orientDbServer1. This will tell Sails to use the orientDbServer1 configuration from connections.js.

module.exports.models = {

  /***************************************************************************
  *                                                                          *
  * Your app's default connection. i.e. the name of one of your app's        *
  * connections (see `config/connections.js`)                                *
  *                                                                          *
  ***************************************************************************/
  connection: 'orientDbServer1',

  /***************************************************************************
  *                                                                          *
  * How and whether Sails will attempt to automatically rebuild the          *
  * tables/collections/etc. in your schema.                                  *
  *                                                                          *
  * See http://sailsjs.org/#!/documentation/concepts/ORM/model-settings.html  *
  *                                                                          *
  ***************************************************************************/
  migrate: 'alter'

};

Configure the database attributes in the profile model

In this step we will add the database fields. Open up api/models/Profile.js.

/**
* Profile.js
*
* @description :: TODO: You might write a short summary of how this model works and what it represents here.
* @docs        :: http://sailsjs.org/#!documentation/models
*/

module.exports = {

  attributes: {
    age: {
      type: 'integer'
    },
    gender: {
      type: 'string',
      enum: ['Male', 'Female']
    },
    haircolor: {
      type: 'string',
      enum: ['Black', 'Blonde', 'Brown', 'Red', 'Blue', 'Green', 'Bold', 'Other']
    }
  }
};

Test setup

Start the sails console

This time we will start sails in console mode, so that we can execute some commands to test the database queries. During the start of Sails the database parameters will be added to the database. Once the console is running you can check if the schema contains the "profile" class and the attributes are present over the OrientDb web interface.

sails console

Execute test queries

Create a new entry to the profile class.

sails> Profile.create({age:22,gender:'Male',haircolor:'Blonde'}).exec(console.log)
undefined
sails> 
null { '@type': 'd',
  '@class': 'profile',
  age: 22,
  gender: 'Male',
  haircolor: 'Blonde',
  createdAt: '2015-07-17T17:49:09.000Z',
  updatedAt: '2015-07-17T17:49:09.000Z',
  id: '#12:0' }

undefined

Check if the entry exists.

sails> Profile.find().exec(console.log)
undefined
sails> 
null [ { age: 22,
    gender: 'Male',
    haircolor: 'Blonde',
    createdAt: '2015-07-17T17:49:09.000Z',
    updatedAt: '2015-07-17T17:49:09.000Z',
    id: '#12:0' } ]

undefined

Part 3: Install Authentication Module

Install Waterlock

If you receive an error executing the commands below try without "sudo".

sudo npm install waterlock
sudo npm install waterlock-local-auth

Generate all files

./node_modules/.bin/waterlock generate all

Configure some test methods

open api/controllers/ProfileController.js

/**
 * ProfileController
 *
 * @description :: Server-side logic for managing profiles
 * @help        :: See http://sailsjs.org/#!/documentation/concepts/Controllers
 */

module.exports = {
    // This action can only be reached when logged in
    restricted: function(req, res) {
        return res.ok("If you can see this you are authenticated!");
    },
    // This action can always be reached without login
    open: function(req, res) {
        return res.ok("This action is open!");
    },
    // This action is used to test parsing the json web token
    jwt: function(req, res) {
        return res.ok("You have a JSON web token!");
    }
};

Configure access

Open config/policies.js.

  /***************************************************************************
  *                                                                          *
  * Default policy for all controllers and actions (`true` allows public     *
  * access)                                                                  *
  *                                                                          *
  ***************************************************************************/

   '*': true,
    
    ProfileController: {
        restricted: ['sessionAuth'],
        open: true,
        jwt: ['hasJsonWebToken']
    }

Here a video tutorial that does basically the same.

https://www.youtube.com/watch?v=2z575YFh9R8

Part 4: Uploading a file

Create the uploadfile html page

Create a new file views/uploadfile.ejs

<!-- enctype="multipart/form-data" -->
<form id="uploadForm"
    enctype="multipart/form-data"
    action="/file/upload"
    method="post">
    <input type="file" name="uploadFile" />
    <input type="submit" value="submit"/>
</form>

Configure the route to uploadfile.ejs

Open config/routes.js. Add the route called /upload-file. The view 'uploadfile.ejs' will be loaded.

module.exports.routes = {

  /***************************************************************************
  *                                                                          *
  * Make the view located at `views/homepage.ejs` (or `views/homepage.jade`, *
  * etc. depending on your default view engine) your home page.              *
  *                                                                          *
  * (Alternatively, remove this and add an `index.html` file in your         *
  * `assets` directory)                                                      *
  *                                                                          *
  ***************************************************************************/

    '/': {
        view: 'homepage'
    },
    
    '/upload-file': {
        view: 'uploadfile'
    }

  /***************************************************************************
  *                                                                          *
  * Custom routes here...                                                    *
  *                                                                          *
  * If a request to a URL doesn't match any of the custom routes above, it   *
  * is matched against Sails route blueprints. See `config/blueprints.js`    *
  * for configuration options and examples.                                  *
  *                                                                          *
  ***************************************************************************/

};

Create upload controller

The code below will create a controller called FileController.

sails generate controller file

Create code in FileControler

Add code to api/controllers/FileController.js.

module.exports = {
upload: function  (req, res) {
    if(req.method === 'GET') {
        return res.json({'status':'GET not allowed'});
    }
    
    // Call to /upload via GET is error
    var uploadFile = req.file('uploadFile');
    console.log(uploadFile);
    
    uploadFile.upload(function onUploadComplete (err, files) {
            // Files will be uploaded to .tmp/uploads
            if (err) return res.serverError(err);
            // IF ERROR Return and send 500 error with error
                      
            console.log(files);
            res.json({status:200,file:files});
        });
    }
};

Reference

http://maangalabs.com/blog/2014/08/12/uploading-a-file-in-sails/

More to follow

This documentation is still under development

Installing AngularJS

Install AngularJS with YeoMan on MacOS X

Pre-Conditions

This tutorial is written explicitly for following versions of AngularJS and NodeJS:

  • AngularJS 1.2.16
  • NodeJS 0.10.30

This tutorial might not work for other versions and will not be updated!

Check if NodeJS is installed:

node --version && npm --version

Install NodeJS

Download and Install NodeJS from following website: http://nodejs.org/

Check if GIT is installed

git --version

Install GIT

Download and Install GIT from following website: http://git-scm.com/

Install yo

sudo npm install --global yo

Install grunt

sudo npm install grunt --save-dev

Re-Install NPM

sudo npm install

Check if everything was installed

yo --version && bower --version && grunt --version

Install AngularJS generator

sudo npm install --global generator-angular

Adjust permissions

sudo echo prefix = ~/.node >> ~/.npmrc

Create project folder

mkdir testProject
cd testProject

Create Angular Project

yo angular

You'll be asked what you want to choose. It's usually a good idea to add all libraries.

Start server

grunt serve

Now a website should open and display the initial page.