

Go Ahead add Some Real Code and Build your Application
Now you have been motivated, your hello world program worked, now we are going to add more functionality to our app.
Create db.js in your lib folder
./lib/db.js
var monk = require("monk"); //for mongodb connection
var wrap = require("co-monk"); // co-monk for wrapper
var db = monk("localhost/loginReg"); //connection to db loginReg
var users = wrap(db.get("users"));
// we are using users collection to save users details
//this will make users available in other pages
module.exports.users = users;
We are using monk and co-monk modules for database connections; we are using Mongodb in backend
We are exporting users to other modules so from any page it could be worked on.
./babel.app.js
//notes: it is compulsory to use babel or bluebird to run our project otherwise you will get
error //running async await functionality
require("babel-core/register")({
"presets": [
"es2015",
"stage-0"
]
});
require("babel-polyfill");
require('./app.js');
Now add the below code in App.js
./app.js
var koa = require("koa");
var app = new koa();
var route = require("koa-route");
var serve = require("koa-static");
var path = require("path");
var co = require("co");
var views= require("koa-views");// to render html swig template
app.use(views('views', {map:{html:'swig'}})); // this will get our html swig
templates from views folder
// trust proxy
app.proxy = true;
// body parser
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());
app.use(serve(__dirname + "/public"));
//routes*/
var homeRoutes = require("./routes/homeRoutes.js"); //getting js in variable
app.use(route.get("/", homeRoutes.showHome));//calling exported function
app.listen(3000);
console.log('Listening on http://localhost:3000');
Now add the code in homeRoutes.js
./routes/homeRoutes.js
//async function to render home.html page
module.exports.showHome = async (ctx) => {
await ctx.render('home');
}
Now to run this app we have to use new command window because other is running by babel
>node --harmony babel.app.js
and run
this will run our project
copy this command and paste it in package.json under scripts
"scripts": {
"start": "node --harmony babel.app.js",
"test": "echo \"Error: no test specified\" && exit 1"
}
Now in terminal type command
>npm start
And your project is started. Before starting our project we have to create our view pages, I am using bootswatch for bootstrap css themes https://bootswatch.com/
./views/layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{%block title%}Title not set{%endblock%}</title>
<link rel="stylesheet" href="/bootstrap.css">
<link rel="stylesheet" href="/costum.css">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and
media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// --
>
<!--[if lt IE 9]>
<script
src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script
src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!—navbar for navigation we are already assigning links for login and logout
it might give error so comment the code if error -->
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-
toggle="collapse"
data-target="#bs-example-navbar-collapse-1">
<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="#">Koa test application</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse1">
<ul class="nav navbar-nav">
<li><a href="/">Home </a></li>
</ul>
<!—if you got error comment this block -->
<ul class="nav navbar-nav navbar-right">
{%if user === null %}
<li><a href="/login">Log In</a></li>
{%else%}
<li><a href="/members">!hi {{user.username}}</a></li>
<li><a href="/logout">Log Out</a></li>
{%endif%}
</ul>
</div>
</div>
</nav>
<div class="container">
{%block content%}
content not set
{%endblock%}
<footer>
<div class="row">
<div class="col-lg-12">
<p>Made by <a rel="nofollow">Websol Software Pvt. Ltd.</a>.
</p>
</div>
</div>
</footer>
</div>
</body>
</html>
Now Add code in home.html
./views/home.html
// extending layout.html this will add navbar, footer and other css used layout.html
{% extends 'layout.html' %}
{%block title%} Login Registration Example {%endblock%}
{%block content%}
<div class="jumbotron">
<h1>Welcome</h1>
<h3>Login Registration Example</h3>
</div>
{%endblock%}
Now run your project, go to browser and you will see a home page with bootstrap css
We are going to use google authentication system for login and registration, this will prevent fake users or users with invalid email ids to register You can create google auth key from here https://cloud.google.com/
tutorials for creating google auth key are in plenty, you can refer them, creating google auth key is beyond the scope of this eBook, do comment or request, we may add that tutorial in our eBook, this eBook will be constantly updated and new things will be added to it.
Although Basic tutorial of google authentication is included
Create your google console project apikey and secret for http://localhost:3000
Create ./auth.js
Add this code in your auth.js
../auth.js
var passport = require('koa-passport');
var db = require("./lib/db.js");
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
db.users.findOne({_id: id}, function(err, user) {
done(err, user);
});
});
var LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(function(username, password, done) {
db.users.findOne({username:username}, function (err,user) {
if(err){
done(err)
}
if(!user) {
done(null, user)
}else{
if(username === user.username && password === user.password){
done(null,user);
}else{
done(null, false);
}
}
});
}));
const GoogleStrategy = require('passport-google-auth').Strategy;
passport.use(new GoogleStrategy({
clientId: 'your-client-id’,
clientSecret:’your-client-secret’,
callbackURL: 'http://localhost:' + (process.env.PORT || 3000) +
'/auth/google/callback'
},
function (token, tokenSecret, profile, done) {
//we are using co function to use generator function yield
functionality
co(function *() {
var user = yield db.users.findOne({google_id: profile.id});
if(!user){
//fetch google profile and save if dose not exists
user ={
name:profile.displayName,
email:profile.emails[0].value,
username:profile.emails[0].value,
provider:'google',
password:'1234',
google_id:profile.id,
imgurl:profile.image.url,
gplusurl:profile.url,
gender:profile.gender,
createdAt:new Date,
bdate:new Date,
about:'hi there',
updatedAt:new Date
};
yield db.users.insert(user);
}
done(null,user)
}).catch();
}
));
What is this auth.js file is for?
This file is for login registration code. We are using koa-passport and passport-local for simple login and authentication.
var LocalStrategy = require('passport-local').Strategy;
This is the local strategy where we are using passport-local. In this strategy we are getting data from login page username, password and sending result. For that first we find record for that username if found then compare with parameter username and password if true then return done(null,user); null for no errors and user to create session, and if not found or not match then return done(err,false); err for any errors found and false for no data found.
Next we are using passport-google-auth for google strategy to register by google account, So that we can make registration process fast instead of filling lengthy forms. Now in google strategy we need ouath credentials for creating google registration.
For that you have to create a project for localhost:3000 in https://console.developers.google.com and create api Key with http://localhost:3000/ and Client ID for Web application with http://localhost:3000 and http://localhost:3000/auth/google/callback and use this credentials in
clientId: 'your-client-id’,
clientSecret:’your-client-secret’,
callbackURL: 'http://localhost:' + (process.env.PORT || 3000) +
'/auth/google/callback'
Now if done with this we have to write call back function for this where you have pass parameters
function (token, tokenSecret, profile, done)
Like this, in this function we are using co() wrapper to write * generator function.
To prevent duplicate registration, in this function we check if googleid already exists
var user = yield db.users.findOne({google_id: profile.id});
If we don’t get any result then this data will be inserted in darabase and user account is created
if(!user){
//fetch google profile and save if dose not exists
user ={
name:profile.displayName,
email:profile.emails[0].value,
username:profile.emails[0].value,
provider:'google',
password:'1234',
google_id:profile.id,
imgurl:profile.image.url,
gplusurl:profile.url,
gender:profile.gender,
createdAt:new Date,
bdate:new Date,
about:'hi there',
updatedAt:new Date
};
yield db.users.insert(user);
}
done(null,user)
And after insert we return the user with done (null,user) for creating session. Here we are retrieving user data from his google account profile like
name: profile.displayName,
email: profile.emails[0].value,
username: profile.emails[0].value,
provider: 'google',
google_id: profile.id,
imgurl: profile.image.url,
gplusurl: profile.url,
gender: profile.gender,
, name, email, googleid, gender, g+ url and image url, and also adding some additional fields to our user profile
password:'1234',
createdAt:new Date,
bdate:new Date,
about:'hi there',
updatedAt:new Date
We are going to keep our default password ‘1234’ for login.
Change your ./routes/homeRoutes.js like this
./routes/homeRoutes.js
var db = require("./../lib/db.js");
var user = null;
module.exports.showHome = async (ctx) => {
if (ctx.isAuthenticated()) {
//console.log(ctx.passport.user);
user = await ctx.passport.user;
}
await ctx.render('home', {user: user});
}
Now we are making some changes in homeRoutes.js
if (ctx.isAuthenticated()) {
user = await ctx.passport.user;
}
here we are checking if user is already logged in then getting user data from passport session in already declared variable user
var user = null;
and passing this user data to home view with await render
await ctx.render('home', {user: user});
By this if there is data then it will be shown on view page else it is null. We have already written a code in our html layout page
{%if user === null %}
<li><a href="/login">Log In</a></li>
{%else%}
<li><a href="/members">!hi {{user.username}}</a></li>
<li><a href="/logout">Log Out</a></li>
{%endif%}
This means if user is logged in then it will show else links username to go to /members page and Log Out to logout. This will navigate to our members get route.
Create login.html and members.html
./views/login.html
{% extends 'layout.html' %}
{% block title %}Login{% endblock %}
{% block content %}
<div class="row">
<div class="col-lg-6 ">
<div class="jumbotron">
<h3>Login to your account</h3>
<hr>
<form action="/login" method="post" class="form-horizontal">
<div class="form-group">
<label for="username" class="col-lg-2 controllabel">Email
:</label>
<div class="col-lg-10">
<input type="email" class="form-control"
id="username" name="username"
placeholder="something@gmail.com">
</div>
</div>
<div class="form-group">
<label for="password" class="col-lg-2 controllabel">Password:</label>
<div class="col-lg-10">
<input type="password" class="form-control"
id="password" name="password">
</div>
</div>
<div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<input type="submit" value="Log In" class="btn btnprimary">
</div>
</div>
</form>
<p>Default Password 1234 </p>
</div>
</div>
<div class="col-lg-6 ">
<p class="lead text-center">
Or
</p>
<p class="text-center center-block jumbotron">
<a href="/auth/google" class="btn btn-danger btn-lg">Sign in with
Google</a>
</p>
</div>
</div>
{% endblock %}
This is a login page with login form with post method and action ‘/login’
<form action="/login" method="post" class="form-horizontal">
This means this form data will be submitted to route.post('/login' method which we are going to write in our app.js file. There are two input fields one is for username and other for password. Names of these input fields are important it should be same as we are writing in parameters of the local strategy in our auth.js file.
<a href="/auth/google" class="btn btn-danger btn-lg">Sign in with Google</a>
There is also a link to google registration, login route, which is used to register and login both
./views/members.html
{% extends 'layout.html' %}
{%block title%} Authenticated Members Area {%endblock%}
{%block content%}
<div class="jumbotron">
<h3>Welcome {{user.username}}</h3>
<!—note: these all functionality we are going to cover in this project so for
future purpose keep this links -->
<p><a href="/edit">Edit Profile</a></p>
<p><a href="/profile">View Profile</a></p>
<p><a href="/delConfirm">Delete Me</a></p>
</div>
{%endblock%}
This is our members.html file which we are going to user to redirect after login is successful. Here we are taking username name of logged in user
{{user.username}}
Like this, this user we will get from passport.user. Remaining links are of no use because we have not created route or pages for that, but keep them as we develop our project this is going to be in use. If getting error then comment it for the time being.
Now in ./app.js we have to add some routes and declarations for login registration.
./app.js
var koa = require("koa");
var app = new koa();
var route = require("koa-route");
var serve = require("koa-static");
var path = require("path");
var co = require("co");
var views= require("koa-views");
app.use(views('views', {map:{html:'swig'}}));
// trust proxy
app.proxy = true;
// sessions
const convert = require('koa-convert');
const session = require('koa-generic-session');
app.keys = ['your-session-secret', 'another-session-secret'];
app.use(convert(session()));
// body parser
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());
app.use(serve(__dirname + "/public"));
// authentication
require('./auth');
var passport = require('koa-passport');
app.use(passport.initialize());
app.use(passport.session());
//routes*/
var homeRoutes = require("./routes/homeRoutes.js");
var loginRoutes = require("./routes/loginR