Showing posts with label nodejs. Show all posts
Showing posts with label nodejs. Show all posts

Tuesday, August 14, 2018

Using Chocolatey for managing NodeJS

What is Chocolatey? Let read here: https://chocolatey.org/about
Install & Upgrade Chocolatey => read here: https://chocolatey.org/install


1. Install NodeJS
Open CMD and the following command:

choco install nodejs -y

It will install latest NodeJS version and npm together.
For installing  long term support (LTS) version of NodeJS, run the command:

choco install nodejs-lts -y

2. Upgrade NodeJS
Run the command:

choco upgrade nodejs -y

It will upgrade to latest NodeJS + npm. In case you want to upgrade npm only, let run PowerShell as Administrator and execute below commands:

Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force
npm install -g npm-windows-upgrade
npm-windows-upgrade
Or

npm-windows-upgrade -p -v latest

3. Uninstall NodeJS
Run the command:

choco uninstall nodejs -y

I love chocolatey ❤

Friday, October 28, 2016

Simple starter kit for building realistic app with Ionic 2

At the point I'm writing this article, Ionic 2 released its RC1 and is going to official release. This article is a continue of my series: Learn Ionic 2 with Authentication by JWT, Ionic 2: FormBuilder and Validator, Build JWT authentication server with Node.js, Express and MySQL. It put all these articles into a Todos System with 2 parts:
  • Server: an enhancement of previous server in Build JWT authentication server with Node.js, Express and MySQL by adding new todos API allowing to get, create new and delete todos based on user role authentication. You can clone / download the source code of this server on my GitHub: https://github.com/vnheros/nodejs-mysql-jwt-auth
  • App: a todo app which allows user login or sign up new account. After login successfully, it will displays a list of public todos or todos of user. User can add new todo or delete an existing todo. You can clone / download the source code of this server on my GitHub (tested with Ionic 2 RC1): https://github.com/vnheros/ionic2-todos-example
I think this is a simple starter kit for you starting your real apps with Ionic 2. Below are important things in this starter kit which I didn't mention in my GitHub.

1. My SQL DB
There are 2 tables: users and todos having script as below:

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) NOT NULL,
  `password` varchar(20) NOT NULL,
  `email` varchar(50) NOT NULL,
  `role` varchar(20) DEFAULT 'Regitered',
  PRIMARY KEY (`id`,`username`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;


CREATE TABLE `todos` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `task` varchar(150) NOT NULL,
  `deadline` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `public` tinyint(1) NOT NULL DEFAULT '0',
  `completed` tinyint(1) DEFAULT '0',
  `username` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;


2. Design of todos app
Below are screens of this app:




The Welcome page containing Ionic login will appear first, then it will check if user is logged in or not by checking id_token stored in local storage. If user logged in, it will move to Todos List page which presents public todos and todos of the user. If user is not logged in yet, it will navigate to Todos Login page for signing in or signing up. Todos List has 2 buttons, one on top for logging out and one in bottom for adding new todo.

3. Step to generate source code for the app
For Ionic 2 RC1, you should install its app-script to avoid some issues when running the app (read this post for more info).

Install @ionic/app-scripts and update your ionic 2:
#npm install @ionic/app-scripts@latest --save-dev
#npm install -g ionic


Generate providers then replace by the source code from my GitHub:
#ionic g provider Auth
#ionic g provider Todos

Generate pages then replace by the source code from my GitHub:
#ionic g page Welcome
#ionic g page Login
#ionic g page Signup
#ionic g page NewTodo

Add folder helpers then add file jwt-helper.ts (used to parse JWT in the app), add folder validators and add file password.ts (used to validate a password input when signing up). You can copy them from my GitHub.

From Ionic RCx, you will need to add pages and providers into app/app.module.ts to use them in your app. See my file on GitHub for example.

There are some another things in the source code which you can discover easily in the source code.
That's for to day and wish you have fun Halloween. Remember turn on the light.
Any comment is welcome.






Sunday, September 11, 2016

Build JWT authentication server with Node.js, Express and MySQL

Node.js is based on JavaScript and V8 JavaScript Engine (an open source JavaScript engine developed by The Chromium Project for the Google Chrome web browser). It supports non-blocking I/O because it is running in single process and dedicated CPU. You can spawn many Node.js processes corresponding with number of CPU cores in your machine. It is unfair to say that Node.js is run faster vs. other web servers because it is very depended on complex of your server application. However in many test cases, they shows that Node.js is very fast especially in running web service (although its startup time is a little bit slow) and how it is easy in coding.

This article is inspired from my previous article using the code from Auth0 for JWT authentication server which users are in memory array. Now I want to rewrite by using MySQL to store users and another purpose is helping beginner of Node.js can get start with Node.js + Express + MySQL.

If you don't know how to start a Node.js application, I recommend you read the popular article "Node.js Applications with VS Code" in VS Code. Assuming that you already read that article, we will start Node.js application with Express Generator as the following steps:

#express mysql-jwt-auth
#cd mysql-jwt-auth
#npm install
#code .

The last command will open mysql-jwt-auth application in VS Code for editing. You will have generated codes like below picture:


OK, now we'll add some necessary modules into this app:
#npm i cors --save
#npm i lodash --save
#npm i jsonwebtoken --save
#npm i express-jwt --save
#npm i mysql --save

After that, open app.js file and add below lines:
var cors = require('cors'); //after the line var bodyParser = require('body-parser');
app.use(cors()); //after the line app.use(logger('dev'));

Change the line:
app.use('/users', users);  ==> app.use(users);

Open your MySQL database and create table users and table quotes as the following:
CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) NOT NULL,
  `password` varchar(20) NOT NULL,
  `email` varchar(50) NOT NULL,
  PRIMARY KEY (`id`,`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `users`(`id`,`username`,`password`,`email`) VALUES (1,'gonto','gonto','gonto@me.com');

CREATE TABLE `quotes` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `content` varchar(150) NOT NULL,
  `private` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Add db.js file into root folder (same level with app.js):
var mysql = require('mysql');
var pool  = null;

exports.connect = function() {
  pool = mysql.createPool({
    host     : 'myhost',
    user     : 'myuser',
    password : 'mypassword',
    database : 'mydb'
  });
}

exports.get = function() {
  return pool;
}


Add below lines to bin/www file (after line: var http = require('http')):
var db = require('../db');
db.connect();


Now we have the db ready for using. Add new file config.json into root folder with content below:
{
  "secretKey": "don't share this key"
}


The above file will keep a secret key for encoding user token after logged in. Open routes/user.js file and replace by new code below:
var express = require('express'),
    _       = require('lodash'),

    config  = require('../config'),
    jwt     = require('jsonwebtoken')
    db      = require('../db');

var app = module.exports = express.Router();
var secretKey = "don't share this key";
function createToken(user) {
  return jwt.sign(_.omit(user, 'password'), config.secretKey, { expiresIn: 60*60*5 });
}

function getUserDB(username, done) {
  db.get().query('SELECT * FROM users WHERE username = ? LIMIT 1', [username], function(err, rows, fields) {
    if (err) throw err;
    done(rows[0]);
  });
}

app.post('/user/create', function(req, res) { 
  if (!req.body.username || !req.body.password) {
    return res.status(400).send("You must send the username and the password");
  }

  getUserDB(req.body.username, function(user){
    if(!user) {
      user = {
        username: req.body.username,
        password: req.body.password,
        email: req.body.email
      };
      db.get().query('INSERT INTO users SET ?', [user], function(err, result){
        if (err) throw err;
        newUser = {
          id: result.insertId,
          username: user.username,
          password: user.password,
          email: user.email
        };
        res.status(201).send({
          id_token: createToken(newUser)
        });
      });
    }
    else res.status(400).send("A user with that username already exists");
  });
});

app.post('/user/login', function(req, res) {
  if (!req.body.username || !req.body.password) {
    return res.status(400).send("You must send the username and the password");
  }

  getUserDB(req.body.username, function(user){
    if (!user) {
      return res.status(401).send("The username is not existing");
    }

    if (user.password !== req.body.password) {
      return res.status(401).send("The username or password don't match");
    }

    res.status(201).send({
      id_token: createToken(user)
    });
  });
});

app.get('/user/check/:username', function(req, res) {
  if (!req.params.username) {
    return res.status(400).send("You must send a username");
  }

  getUserDB(req.params.username, function(user){
    if(!user) res.status(201).send({username: "OK"});
    else res.status(400).send("A user with that username already exists");
  });
});


At this time, we can use above code for authenticating user. Key the command npm start and use Postman tool to check what the server response. Here is my example:

That's fine, so we are going to add routes/quotes.js file to illustrate for anonymous request and authenticated request in reading quotes. This file has simple content as below:
var express = require('express'),
    jwt     = require('express-jwt'),
    config  = require('../config'),
    db      = require('../db');

var app = module.exports = express.Router();
var jwtCheck = jwt({
  secret: config.secretKey
});

function getPublicQuotesDB(done){
    db.get().query('SELECT * FROM quotes WHERE private=0', function(err, rows) {
        if (err) throw err;
        done(rows);
    });
}

function getPrivateQuotesDB(done){
    db.get().query('SELECT * FROM quotes WHERE private=1', function(err, rows) {
        if (err) throw err;
        done(rows);
    });
}

app.get('/api/public/quote', function(req, res) {
  getPublicQuotesDB(function(result) {
      res.status(200).send(result);
  });
});

app.use('/api/private', jwtCheck);
app.get('/api/private/quote', function(req, res) {
  getPrivateQuotesDB(function(result) {
      res.status(200).send(result);
  });
});


Don't forget to add below lines to app.js file to include above quotes.js:
var quotes = require('./routes/quotes');
app.use(quotes);

OK, let use Postman tool to check if the api gets quotes working as expected. Here are my results:



As you can see, request /api/public/quote works fine. But you will get a complain "No authorization token was found" if you request /api/private/quote. When you add Authorization header with your token for it, it runs ok soon (last picture).

That's all for tonight. Bye!
You can find source code on my GitHub.

Subscribe to RSS Feed Follow me on Twitter!