hi in this tutorial i'm going to show
you how to develop a web application
using node.js and the express.js web
framework we will then deploy our
application to aws using elastic
pinstalk environment we will develop a
landing page where we collect and manage
sales leads you can freely use the
resulting source code as a starting
point to develop your product and we
will cover all of the concepts that you
need to know to build a fully fledged
web application using node.js we assume
intermediate programming knowledge but
no background in web application
development or not js okay let's get
started so a little bit of background on
node.js many years back developer ryan
doll explored the idea of using
javascript for server-side programming
with the main motivation that existing
http servers could not handle lots of
simultaneous connections efficiently
meanwhile also google's chrome browser
team developed a new javascript engine
from scratch called v8 and the unique
property of v8 is that it was built to
be much much faster in interpreting and
running javascript compared to the other
browsers and nodejs took google's
optimize v8 javascript engine for
server-side programming also creating a
setup that allowed for much more
scalable handling of requests and also a
package manager for managing the open
source javascript libraries was
introduced called npm and node.js was
worn now before we install node.js we're
going to start by installing a script
called nvm so go ahead and type nvm in
your browser and click on this link and
vm is short for node version manager
it's a script to manage multiple active
node.js versions on a single computer so
let's go ahead and scroll down to copy
and paste the install script for nvm and
we'll paste it on our terminal
now i already had nvm installed so this
step may take a little longer in your
case and what you need to do is close
and reopen your terminal
so that the nvm script can initialize
while your terminal starts you can check
that your installation was successful by
typing nvm
version we're now ready to install
node.js so let's go back to nodejs.org
we're interested in the long term
support version of node.js and as of
this video it is
10.15.0 is the version that we need so
we go back to our terminal and type nvm
install 10.15.0
now this step may take you a little bit
longer you should have now node.js
installed and being actively used just
for the sake of showing you how it works
you can also install other node.js
versions let's go for 8.11.3 for example
and you can switch between node.js
versions by typing nvm use so let's
switch back to using node.js 10.15.0
now for our application we're going to
use express.js so let's go ahead and
visit
express.js
express.js is a web framework and the
power of it is in its simplicity you can
develop very complex web applications
yet it is a minimalist web framework
that is very easy to grasp and this is
the install command for express.js but
we're going to use another tool called
the express generator that will give us
a good starting point and a directory
structure so let's go ahead and copy and
paste this command in our directory to
install express generator now here in
this command npm as i mentioned is the
node package manager we will use this to
install packages and here the dash g
stands for a global install which means
the installation is going to happen the
computer-wide and not just one
particular project so i'm going to press
enter now
and now we can go ahead and run express
generator to generate our application
and a useful directory structure so i'm
going to copy paste this command here
dash dash view equals pug means we're
going to use pug as our html templating
engine
so i'm just going to press enter and we
have now created a directory structure
for our application now that we have
generated a skeleton directory structure
for our application i want to go over
each folder we created so let's go ahead
and start our text editor
and let's take a look so under my app
the public folder contains our assets
assets are static files that your html
files makes references to each html file
will refer to certain images such as
logos and some javascript files that
need to be run on that webpage or style
sheets that describe the style on a web
page the rouse folder contains the
router logic we will get to routers in a
little bit and it's one of the key parts
of our application and finally views
contain the representation of each
individual html page in our application
notice that these are named pug files
each of them get converted to separate
html page the bin www file contains the
initialization script for our web server
and one of the notable files is app.js
this is the main entry point for our
entire web application and also we have
the package.json file which is a recipe
that contains the list of open source
packages we need to install to run our
application now let's go ahead and
install these packages and run our
application as it is so we go back to
our terminal cd my app and we type npm
install
we're pulling and installing all those
packages this file contains not just the
packages that we need but also npm
allows us to fetch all the dependencies
that these packages have
and now in order to run our application
we need to type this command and once i
press enter the web server is running on
port 3000 and when i visit localhost
3000 on my browser i get to see this web
page served if we go back to our source
code app.js is the most important file
that we care about app.js defines our
web application and node.js express.js
applications are monolithic meaning that
every piece gets put together into a
single application and let's see how
that works we first import modules using
the require statements and typically
these modules are those ones that we
find under the package.json file these
modules here you will see that they have
been imported and assigned to
variable instances
the one we're interested in is this
express variable as you see the required
statements includes the express package
assigns it to a variable and then later
on we call the constructor for express
and assign
the result to a
variable called app an app is an
instance of an express application
typically this is a
vanilla instance and then
we
make
certain method calls to modify and
configure our application and also use
and include other modules here we first
set that the views are included in a
directory called views
this is what this line does and we have
as you can see a fuse directory here and
next we set that we you are going to use
pug as our view engine so the app
instance that is unmodified and new gets
modified by these set calls and then we
have certain use method calls
where we define further configuration
and further components that we're going
to use and one of the notable ones is
the index router object that we have
defined in this project if you go up
here we use the require statement to
include an index.js under the routes
directory whatever that has been
exported from this index.js file is
assigned to an index router variable
and this instance is then used for the
path that is slash so this line means
that our application is going to use
index router for the slash route and
that's how we also connect pieces of our
application into one monolithic instance
because index router was defined here
under index.js and it has been included
from app.js
let's take a look at how the
route object is defined if we go under
routes and index.js again we are
requiring the express package we have a
variable called express and then
we call a router to create an instance
of an express router and just as we did
here
the router instance here is a vanilla
instance it hasn't been modified and
then we make some certain method calls
to define it further in this particular
case we're defining a get method and how
to handle this slash path with a
function and then we export
the router instance that we have created
to be included by another module and
app.js includes that router here
and that's how we connect it and
the router object to recap is a vanilla
instance then we make some modifications
on it and then we export it and this
pattern is used throughout the
application this is how you
divide your application into
separate instances now let's take a look
at what a route handler is and how it
works here we have a router variable
that is an instance of an express router
and this router variable has several
components that we care about the first
one is that we're making a call to get
and this defines that the route handler
is associated with the get http method
and then the second component we're
interested in is the path so typically a
router will match a particular path used
in a url
and then finally there is a handler that
gets called if a path is matched to look
at it more closely if this is our url
the first section defines the protocol
being used and the second one is the
domain and then finally after the slash
here we have a path component so
a router
object will look at this path and see if
it is a match for the path that it has
in its own definition finally the router
will call the handler that's associated
with it the last bit of detail here is
that the get method here is defining the
http method that this route handler is
limited to it only responds to this get
method if there are no routes that match
for a given path or http method our
application generates a 404 error which
means not found so as a recap under
routes index.js we're creating an
express instance and then we're calling
express.router to create a router
instance and on this router we're
defining that for the http get method
if we are looking for the path slash and
it gets matched we call this function as
our handler for this route
and under app.js
we have an index router representing our
exports from routes slash index file and
then we have this statement here app.use
and for the slash path we're using index
router effectively meaning that when we
type this root
path with no slash or slash it means the
same thing essentially and when we press
enter we call the
route handler that's defined here which
renders our index page and that's how
essentially our route handler works
before we dive into source code and
define routes and handlers let's cover
what an http request is and how a
request sequence works the http short
for hypertext transfer protocol defines
multiple methods for browsers to
communicate with web servers and
the http methods allow the browser to
take different actions
the get method simply fetches a resource
from the web server such as a web page
when we make an http get request
the server typically responds with a
resource such as a json object or an
html file and in our current scenario we
are interested in sending back an html
web page and we use the express js
specific method called res.render a
restart render will generate an html
page and our web server will respond
back to the browser request with a web
page and the other
method we're interested in is called
http post this is typically used for
submitting data
to a web server when you fill out a form
on a web page and you press the submit
button the data is sent to the web
server and typically an http post
method is used there are multiple http
methods and what method is to be used is
defined in the form definition on that
particular html page but most of the
time and almost always a post request is
used and
once the server receives the post
request it does something with the sent
data such as updating a database and
then the server typically calls the
res.redirect method again this is
specific to express.js
to redirect the browser to another url
or path
so the server responds with a redirect
after processing the data back to the
browser and finally the browser will do
another http get request as a third step
fetching the route that it has been
redirected to now
there are a few more http methods but
this gives you the foundation for
developing a rich web application now
you know enough to develop routes route
handlers and develop your application
one of the issues with our route handler
is that the logic that matches a url
pattern is here but also the handler
function the handler logic itself is
defined as part of the root handler
and what we want to do is separate these
two so that we have a modular approach
so we go to our terminal and i'm going
to create a directory called controllers
controllers essentially are a collection
of root handlers i'm going to copy this
function from here and place it under
controllers in a new file
save it here
and
give it a name called index and save it
with the name index.js
and if i go back to the routes
and define index
as an instance of what we have exported
from our controllers index.js file i can
now refer to
the handler
that i've defined
from this route file so if i go back to
controllers as a recap we have an
index.js and we have a method called
index that we're exporting as our
handler and
under our routes let's save this file
again
and under our routes we are importing it
as a variable instance called index and
we're assigning the index handler for
this route let's now save our
application restart it and see if it
will work
so i'm restarting the application and
typing this url and it's working so
controllers allow us to separate handler
logic as you see in this example from
the root handler logic and we're going
to build many more of these controllers
now let's take a closer look at what our
controller function does so if we go
under controllers index.js
we named our function as index and the
only
call it has is to a call called
res.render the resident render call
renders an html page from a template the
first argument is the name of the
template file which is index if you see
under views directory we have a file
called index.pug and the second argument
is a javascript object with a key value
pair the key is title and the value is
express now under app.js we did define
our view engine as pug and we did define
that the views are located under the
views directory so express.js knows
where to search as the starting point
for view files so when we pass index as
the first argument it will go and look
at the views directory and find that
there is an index.pug file here and then
pug will convert this template into a
real html if we look at this second
parameter again title colon express we
also pass this as a parameter to pug so
if you look at index.pug it will use the
variable and replace it with its value
there are two cases where the value is
being used here we'll get to this when
we look at pug in more detail but
essentially our controller function
simply renders an html page it responds
with a html page back to the requesting
browser now is a good time to use
version control and checking all the
files that we have created so i'm
assuming that you've installed git and
i'm going to initialize a git repository
here by typing git init db now we've
initialized the repository and you can
check that we have created a dot git
file in the current directory that
stores all the files by our git
repository and now i'm going to check in
all the files but before i do that
i need to create a file called git
ignore under my app let's create that
file and type node modules in it because
node modules
are installed open source files they're
not part of our project and git ignore
file having node modules will exclude
those files all of these files from our
version control typically any file that
gets auto generated or external to your
repository you should exclude by using a
git ignore file okay going back to the
terminal i'm going to make my first
comments by typing git add dot dots here
representing the current directory so
i'm going to add all the files in my
current directory to the git index and
commit them by typing git commits dash a
meaning commit everything that is in the
index to git
so as you can see we have a bunch of
files being committed and we're also
including the get ignore file so let's
type
initial comment
and save and exit and we have
essentially committed our first change
to our git repository to get the full
source code for the tutorials if you go
to this website and scroll below you
will see posts with programming snippets
as well as the link to the source code
for those tutorials and if you have
questions you can click on this button
on the same page become a member it's
free and then you'll be able to add
comments to tutorials and get answers
now one of the problems we have is that
every time we make a modification in one
of our source files we need to restart
our web server
because the changes made to source files
are not being recognized and in order to
remedy this problem there is a tool
called node mount that we are going to
install so i'm going to stop our web
server and i'm going to install nodemon
by typing
npm install nodemon and then also typing
save
dash dev
what this does is the save dev will save
nodemon as a developer dependency
meaning that we only need to install it
when we are developing our application
so if we go under
package.json we now see that nodemon is
a developer dependency
and now we need to modify this line
so that in the case of an environment
where we're in production we're
still using the standard node command
but in case of development we're going
to run nodemon instead that monitors for
changes in source files and restarts our
web server so for the start scripts i'm
going to go ahead and type if the
environment is production then we use
node.bin www else we use nodemon bin www
and then fi
now this should work and we are going to
use nodemon to monitor our web server so
let's go ahead and try running this
okay as you can see nodemon has started
and when we make any source code changes
it's going to automatically restart our
web server now is a good time to make a
git commits because we've installed node
mode so i'm going to do git add
package.json and then git commit dash m
install nodemon
now i'm going to cover the most common
web application development pattern
where we are going to build a landing
page with various routes to collect
sales leads manage them view them and
delete them and edit them let's go ahead
and rename the variable index as landing
because we're going to build the landing
page and our controller is going to be
called landing and we're going to name
our first method that gets our landing
page as get landing so if we go we save
this file and go to controllers index.js
let's let's rename this file as
landing.js
and
first function is going to be get
landing and also let's rename the view
now when we fetch this file we're going
to display a form where if a visitor
likes our service or our value
proposition they will enter their email
address and send us that information in
a form so i go under views landing that
pug and right below this paragraph i'm
going to
design a form
the the form element takes one parameter
called the action when we submit the
form which path we're going to use is
defined by action so i put a comma and
for the second parameter i'm going to
use the method called post when you
submit a form the method that has been
defined in the form is the one that the
browser will use for making the request
so we're interested in using the post
method and i'm going to define an input
element of type email
and we're going to use a placeholder
let's write here enter
your email address notice how there is
an indentation here pug nests html
elements by using indentation so inside
form we have nested an input and also
typically we want to nest a button
inside a form so that the button is
associated with that form so i'm going
to define a button elements of type
submits when this is a submit button
that indicates that we're going to
submit the form that the button is
nested in we're going to use a name for
the button called submit and i'm going
to now save this form
let's make sure all of the files are
saved and if i now restart my
application
i should see the form being served if i
press enter here right so we have this
enter your email address form with an
input and then a submit button we're
also going to commit our changes by
typing git add because we renamed some
files we need to explicitly add let's do
git add views
git add controllers
let's see if we have captured all the
files i do git commit dash a to commit
all the changes landing.pog has been
registered as a new file and so is
controller landing.js but we missed
views landing that box so i'm going to
explicitly add that file landing.pug
okay now if i commit
we should be covered with all the files
that we have renamed and added in git so
i'm going to write a commit message
landing page getting started
and first form typically in git you
first summarize your change in a single
line and then you would leave an empty
space and then include further
information in the second paragraph but
at this point we don't need to mention
much i'm just going to leave it at the
first line
now that we have defined this form we're
going to develop our first post route so
i go to routes index.js
and include a new router with the post
http method and then i'm going to use a
new handler called landing.submit lead
because we're looking for sales leads it
is called submit lead i'm going to save
this file go to the controllers
landing.js i'm just going to copy and
paste this first handler that we had and
i'm going to name the second one as
submit lead when we submit our form from
landing.pug there is this input element
we forgot to name it so i'm going to
define a name for it called lead email
when the form is submitted from that
browser we're going to be able to access
the value inside this input element with
the name lead email by going to our
controller let's delete this statement
here we're going to print out
the input element that we have received
lead email and the way we do that is by
using the body parser library we are
going to do rec dot body lead email to
print out the value i believe i need to
include the package called body parser
in app.js for this to work but it turns
out express.js already includes this
functionality this allows us to retrieve
the values for input elements when there
is a handler for a post request if we
simply do
rec.body.lead email we're going to be
able to access the value inside the
input element now this handler is
successfully reading this data but we
can't leave it at that we need to
conclude the request so we're going to
do a res that's redirect
and we're going to use the original path
of slash so that we go back to the uh
landing page for now so i'm going to
save this and
we're already running the application
let's see what happens if we submit an
email address here
my email at
domain.com so i'm going to press submit
as you can see the browser was
redirected to the same page but let's
see what happened in our console we were
able to receive the value and print it
let's check in all the changes we made
so let's go to our terminal and type git
add controllers landing.js git add
routes
index.js and we also modified our view
file so we're going to do git add views
landing.pug and comment landing page
post route to submit email
so we're able to receive
data in our application but we're not
able to do much with it so we're going
to install a database an sql database a
particular postgres database for our
application go ahead and open up your
browser and type homebrew homebrew is a
package manager for mac os and one of
the packages maintained is the
postgresql package so you can copy and
paste this installation script on your
terminal if you're on a mac os to
install homebrew let's go ahead and just
do that and it's going to install a
command line tool called brew which will
allow you to then install various
packages including a postgresql now i
have it already installed so i'm going
to skip this step and assuming you have
installed this we can then install
postgres by typing brew install
postgresql so after you've done that you
can start your database by typing brew
services start postgres ql this is going
to start the postgres process in the
background on your machine so that you
can connect to it and create databases
manipulate tables do things with it so
i've already run this command so i
already have my database running we're
going to use a tool called psql to
connect to our database and make some
changes so i'm going to type psql
postgres to connect and if everything
goes well you should see the postgresql
prompt and now we're ready to create our
database first we create a user that can
access that database by typing create
role express mvp db user i'm assuming
here that i'm going to use the name
express mvp for our application so i'm
just adding a
db user for that and with login password
let's make the password simple for now
and press enter and now i'm going to
create our database by typing create
database express mvp db in case you want
to delete these roles or databases and
redo the same commands you can do that
by typing a drop database or drop role
so we're now ready with our database i'm
going to quit psql by doing the control
d we're done with our database setup now
we're interested in using a library for
accessing our database from javascript
and manipulating data and for this we're
going to use an object relational mapper
library shortly called an orm we picked
sqlize as our choice of orm
if you go ahead and type sqlize in your
browser you're going to find a website
for it as sqlize is a stable and popular
orm for node.js and it will work well
for most of our needs and rm greatly
simplifies the type of queries you have
to write for manipulating database
tables and rows instead of typing long
error prone sql queries and rm lets you
generate those queries by writing
javascript okay so let's go ahead and
open up our terminal again and type npm
install
sqlize this will install sqlize as a
package i recommend doing dash dash save
so that it's saved to our package.json
file we're also interested in the
database driver library in node.js for
postgresql which is simply called pg so
i'm going to go ahead and type npm
install pg
save as well
sqlize will invoke pg in order to access
the postgresql database this is a low
level library for accessing postgresql
databases the other tool that we need is
a command line tool for sqlize called
sqlize cli so i'm going to install that
as well by typing npm install sqlize
cli and i'm going to use dash g so that
concludes our installation for postgres
and sqlize now we're going to create
some configuration files so that our
application and sqlize can access our
database and for that we're going to use
the tool a sqlize cli
but before we start we need to first
create a configuration file for sqlize
cli so that the default paths we use are
going to be defined let's go ahead and
create a file called dot sqlize rc in
the root of our project typing a touch
dot
sqlize rc and let's open up our editor
when we open a sqlize rc we see certain
paths defined let's remove the db path
and let's keep it empty for now we want
to create these directories directly
under our application root folder so
that they're accessible easier with one
less step so let's go ahead and save
this file and now we're ready to
generate
some files so i'm going to by sqlize
init and we have created several folders
the config config.js is the one we're
interested in this is defines the
database details let's open up our
editor again and go to config
config.js we have three environments
defined here one for development test
and also one for production so i'm going
to type here module that exports equals
and for developments we defined the
database username as express mvp dash db
user as our password we defined 123.456
and for our database these are the users
and database we created using the psql
command previously so
we're going to type express mvp
db and our host is
12701 this stands for the localhost the
database we're using is postgres so
we're going to use the dialect postgres
here there's one more parameter missing
here
the port parameter typically
for a postgres database that is a 5432
i'm currently not going to touch the
other environments and going to save
this one here so we should be now
ready to access our database from sqlize
using our application now i'm going to
go back to the terminal to commit some
of the changes that we made so far we
installed sqlize and the pg library so
we've modified our package.json file
let's go ahead and create a comment for
that change
we have added sqlize and pg packages and
i'm going to save this comment we've
also defined a sqlize.rc file so i'm
going to add that one as well
and commit this change
configuration file for sqlize
cli
and i've also created a configuration
file for our database connection so i'm
going to commit this file with git add
config config.js there's also one more
file that i'd like to introduce to you
briefly under
models when we ran sqlize in it we
defined the file called index.js this
will initialize sqlize when we run our
application it takes the environment
that we defined under config.js and then
creates a new sqlize instance using the
database credentials that we have
created so this is the initialization
file that was auto generated when we
typed sqlize init so i'm going to check
this file in as well and the file name
is always index.js under models and this
is a specific file just for initializing
sqlite so i'm going to
commit these changes so we added
configuration file for
sqlize and the script
as a recap for where we've left off we
can visit our landing page and then
submit an email address to our
application
and display the email address collected
as a console log
now that we have installed our database
and installed sqlize orm and configured
it we're ready to define our first model
as well as the first migration so let's
go ahead into our text editor and create
a new folder called migrations and let's
create a new file under the models
directory named
lead.js since we're collecting sales
leads our table and model will be named
leads migrations allow us to create
recipes to take our database state the
database definition from point a to
point b for example right now we have no
tables in our database even though it
has been created and with a migration
recipe we will be able to create our
first table that represents our sales
leads and we will run that migration to
create our first table and start
accessing it and the model definition is
used by sqlize to
create to generate the methods for
accessing the table and to update the
table to take database actions on the
table such as creating rows deleting
rows updating rows and fields and in
contrast migrations are used for
manipulating the database table
definitions themselves such as creating
a table adding a new column or changing
the type of the column in that table the
migration file that we're going to
create is highly specific to sqlize
sqlize has low level methods for
accessing and manipulating a postgresql
database but the migration itself is a
file a recipe that's specific to sqlize
and so is the model that we're going to
define so let's go ahead and create a
new migration file and let's define our
first table i'm going to copy and paste
this code that i have already prepared
as our first migration let's first save
this file migrations are a sequential in
the sense that they need to be run in
order they don't make sense if they are
run without an order so we need to order
them by the file name and we do that by
including a date starting with the year
a month and the hour and even the
minutes when the migration is created so
as of now we're in january 4th 2019 so
i'm going to name my migration as
2019 0 1 0 4 and then the hour is 19 17
and i'm going to include the action that
this migration is going to take which is
creating a table named lead so create
lead table and then finally that's a js
here is our first migration saved and
the migrations are bi-directional so you
can apply a migration represented by the
up method and then you can roll back a
migration by using a down method so in
this case the up method stands for
creating a new table called leads with
so and so fields and then the down
method or action represents dropping the
table will effectively cause the table
to be deleted from our database now if
you look at the fields that are being
generated we first obviously have an id
field and id represents a unique column
in our database and it's represented by
universally unique id type and sqlize
has that type built in for us and
typically we need a created ad and
update that field for each row when a
new row is created this date will be
relevant and each time a row is updated
this second field updated at is going to
be irrelevant and finally the actual
field the data that we were collecting
in our application is an email address
so we're including a field called email
of type sqlize string
so we have saved this migration we can
go ahead and run it by typing sqlize db
migrate the command has succeeded which
means we have created a table called
leads in our database now we need to
define the sqlize model definition for
the table we just created so let's open
our editor and create a new file under
models called
lead.js i'm going to copy and paste the
definition that i created earlier for
this this javascript model file is
specific to sqlize sqlize will generate
the methods it needs to access the
database table by
using this model definition we define an
id field in the model which is a primary
key and then we define an email field as
well which is of type string notice how
these fields match the migration we just
ran for the leads table
and we omitted the created that and
updated that fields in the model because
sqlize assumes they always exist when we
run the application sqlize will run
models index.js if you look at this for
each section it will go over each model
definition under the models directory to
import and use for accessing the
respective database tables under models
directory for each database table we
define a model such as the one we
created for lead.js for the leads table
and sqlize will go over each of those to
generate the methods so that it can
access those tables in order to achieve
this we need to go to the initialization
file bin slash www and here initialize
sqlize for that we need to first create
a variable called models and import the
models directory
and these three lines start our server
listening on a particular report we're
going to modify this code a little bit
and we're going to type return
models.sequalize
sync and then
result
going to
cut and paste this portion inside the
body of this call
okay we're now ready to further develop
our application and run sqlize queries
before we go any further let's check in
the files that we have just created so
i'm going to add the migration we
created
and commit this file
create migration for
leads table for creating
leads table
i'm going to check in the model as well
it's add models
lead.js
we're also going to check in the changes
we made on the initialization file
bin slash www
initialize sqlize in
bmw
now that we have a database set up we
can implement the post route where we
will save an email address to our
database so let's go and open up our
editor and go to controller slash
landing.js
we're going to modify the submit lead
handler to save the email address
collected to our database so let's go to
the top and then type const models
equals require
dot dot slash models
models gives us access to the sqlize
methods for the models that we have
defined
and i'm going to type return
models that lead that create
note that create is a sqlize method
and for the email field we're going to
use the value we've obtained from reg
body lead
email
then
take the results
and redirect
back to
the
landing page
and let's delete this last line and the
first line
save
and rerun our application
if i go back to the
landing
page and type an email address here
username at email.com and submit notice
that the browser reloaded the landing
page and that's because
of the res redirect here and i'm
assuming that the create call has
succeeded if you go back to our terminal
we see this sql statement here generated
by
sqlize run by sqlize
we're inserting a new row into the leads
table particularly the id email created
that and updated that fields new a
unique id for the role and then the
email
address we just submitted
and then the dates
so we've successfully saved the email
address in our database let's commit the
changes we made so i'm going to type git
add
controllers landing js and then commit
the change
save leads collected on landing page
we save
email addresses collected back to the
database
we're going to implement the most common
web development pattern shortly known as
crud which stands for create update and
delete
we've already done the creation of leads
with this route and now we're going to
define new routes that allow us to do
listing editing updating and deleting of
leads so and the first one we will cover
is for listing delete so let's define a
new route
with the path slash leads
and
the handler called as show
leads and let's save this file
and let's go to controllers landing.js
to define our new handler let's copy and
paste the first one we
created
let's name it as show leads
now all we need to do is fetch the leads
from the database and for that we're
going to call
models
lead
dot find all
and then we will be returned an object
let's name it as leads
and let's cut this line with the res
render and paste it inside the body here
a few things to note this
call here is a promise and we're going
to cover promises in detail later but
for now what you need to know is that
this call is going to execute
asynchronously and the then here
ensures that the results within this
body are available after the execution
of this call has completed so there's a
guarantee that
this body is going to be available after
this execution
even though the call is asynchronous and
we'll get to those later and
the file all method is defined by sqlize
and also the leads object here contains
the rows returned from the database and
also the methods to access those
rows
so as you can recall the render method
the second parameter is
an object passed to our view file we're
going to define a new key here called
leads and assign it the value of our
object leads
and save this file and one more thing to
note is that this view file usually
typically we use a different view file
for each purpose but for the time being
we're going to use the same landing view
file to also show the collection of
leads
now let's go to
viewslanding.pug
we're going to type if
leads pug will check that if the leads
variable is non-zero it's going to
include the rest of the html snippets
let's type if leads and then let's
define a header here called
with the text leads plug also has the
capability of iteration we're going to
do for lead in leads
note that leads is an array of objects
of type elite we're going to create a
paragraph
and type lead.email
now pug considers that anything of that
comes after the p is text we don't want
to display this as text and we want to
use the pug way of syntax of
dereferencing this variable which we
used here
by typing hash open curly brackets and
then close curly brackets so let's save
this landing file
and go to
our terminal
our application is still running so
let's go to our browser
and type localhost 3000 there's one more
thing we want to do
let's go back to the landing.js
controller now instead of redirecting to
the slash route we actually want to
go to the leads route when we submit a
new lead so that's the change we make so
that the
this new route that we defined is going
to be triggered which we'll call this
show leads function
okay so if we go back to our browser let
me submit a new email address
lead one email.com and when i submit
this
i see the list of leads on the same page
and notice how the browser
went to the slash leads routes
because of the change we just made
so let's check in the changes we made so
i'm going to do git add controllers
landing.js git add route
index.js and
add views
landing.pug
implement leads routes
show a
collection of leads
upon submission
now we want to take a look at the
details of each individual lead so let's
define a new route
called
slash lead slash
colon
lead underscore id and let's define a
handler
landing that show underscore lead
now two interesting things here
firstly we defined slash lead slash as a
unique path component to match
individual leads and notice how this
path is unique and different than the
other routes we defined we will handle
all details of an individual lead under
slash lead slash path component which
gives us sort of a namespace to work on
individual leads
the colon here
defines lead id as a parameter as a
request parameter that means whatever
that comes in the url you type in the
browser after slash lead slash is going
to be captured in a request parameter
named lead underscore id
and we can then access the value of this
parameter in the root antler
show lead
now let's go to controllers landing.js
and copy and paste one of the handlers
we already have
let's name it as show lead
and what we need to do now is query the
database for a lead with a given id so i
need to do return models.lead.find1
and then
the where clause
helps us
query for a particular field and we're
going to use the id field and we're
going to pass the request parameter that
we received
named as lead id
to find the particular the lead record
in the database
corresponding to our lead
now
this will return a lead value
let's go ahead and delete this portion
and here we're going to
do res render
we're going to define a new view file
called lead and pass an object with key
lead
assigning it the database object that we
received
now let's save this file and go ahead
and create
a new file under reviews called
lead
let's copy the
initial portion of
landing that bug
and let's define
an h1
lead header and let's simply define a
paragraph with the lead information
lead.email
now let's go to landing.pug we want to
give the user an opportunity to click on
a link that takes us to the individual
details page for that link and we don't
have that link here so i'm going to add
that to this paragraph
but i would like to display both the
lead email and also that link on a
single line the same line so i'm going
to
nest the link and the email under the
same paragraph as a reminder we
nest html elements with indentation in
pug so i'm going to first define
under the paragraph a span elements
that will display our email and also
um this character that i'm typing is
used for
text and also to display spaces in park
so i'm going to include one space
character
and
define our link with the anchor tag
with an href property of slash lead
slash
and now here we already have access to
the lead object that has been obtained
from the database so we can
include the id of the lead here by
typing lead.id
and we are going to
use the text details
in the link
so now
this link is going to point at the path
slash lead slash plus the database id of
the lead so let's save this and run our
application
everything seems to work fine so let's
open up our browser type localhost 3000
let's submit a new lead
new leads at
domain.com and
see that we're able to
display
both the leads and also the details link
for those leads i'm going to click one
of them we're now navigated to
that path and we're able to display the
lead information
now let's check in all the changes we
made
it add views
it adds controllers
and routes
and then if we commit now
add a new route to display
lead details
let's go back to routes slash index.js
and we're now going to define the routes
for editing individual leads so let's
type router that gets
slash lead slash colon lead underscore
id and we're going to define a new
action for this particular lead id which
is going to be slash edit
and we're going to define a new handler
with landing dot show
edit
lead
now this is a gate route which means
that we're going to fetch a new web page
for the purpose of editing the lead id
so we're going to deliver a form
that contains information about this
lead id by using the
show edit lead handler
and let's type router.post slash lead
slash colon leads id slash edits
and define a new handler called edit
underscore lead here the first route we
defined shows the form for editing the
lead id and the second
route we defined which is a
post
submits the form to edit the lead id now
there's one key point here we are highly
interested in defining the same path
component for the get and the post
routes
and this is because on an error when we
handle the post request if we re-render
the same page we want the url in the
browser to match the original get
request
we're going to go into more detail about
this when we cover error handling
now let's get started by creating the
link that will take us to the edit route
for the lead for that let's open up
views
lead.pug
now we're going to modify this
by creating a span under the paragraph
and we're also going to create a link an
anchor tag
with an href of slash lead slash
plus lead.id remember that we have the
lead database object available to us so
we can reference its id and also we're
going to add the
slash edit path for editing the
lead
now let's
write
edits
for this link
and save this file
and notice how the value of this hf
property corresponds to the get route we
defined here
now let's define the handler for this
show edit lead route by going to
controllers and landing.js and let's
copy and paste one of the handlers here
and call it show edit underscore lead
now this handler also obtains one lead
record from the database by using the
lead id parameter and then we're going
to instead of displaying the lead we're
going to display a form
where we can edit and submit the updates
on a lead so i'm going to call this
edit underscore lead
and we're going to
use a directory called lead
for
all the view files where we manipulate
each lead so i'm
going to finally call this lead slash
edit.leads now let's save this
controller and
create a subfolder under views
called lead and also create a new pug
file
called
edits underscore lead dot pug
now let's go to landing.pug and copy
the beginning portion
to edit lead
and now we're going to create a form
under edit lead where we will
modify we will have the opportunity to
modify the lead
so we can copy some code from
landing.pug we or where we already had a
form i'm going to copy this form and
input element and the button elements to
edit lead
now the action for our form needs to
reflect the route that we defined here
which is lead slash leads and then the
lead id and edit so let's go ahead and
add that here
we're going to use plus lead.id and then
plus
slash edit
and the method we're using is post
method and we're still going to use the
same name as lead email in our input it
is of type email if we need we have a
placeholder if the
lead field is empty
and then let's call this button
save
now rather than an empty form we want to
show the existing value of the lead so
we're going to add a new property in our
input element called value and assign it
with
lead.email which we will receive from
the database
now let's save this file
because this file is one subdirectory
under views because we created this lead
directory and we are referring to
layout.pug at the beginning we need to
update also our reference to go one
directory level below now if we go back
to our index.js file we haven't defined
the root handler edit underscore lead
for the
post route so let's go to our
controller's landing.js
and define a new route called
edit lead
and let's delete the body
now we have access to the leads
id
by using
rec.params.lead underscore id because
this was available to us in the route
path
we also have access to rec
body
lead underscore email the actual updated
field
and that comes from the edits lead form
the name of the input element was lead
underscore email so we're going to use
these fields to first retrieve the
object by using its id and then we're
going to update its email field by using
lead email let's go ahead and type
return models dot lead
that update
email
rec
body dot
lead underscore email
and we're going to use a where clause
we're going to
ask for the id field using rec params
lead underscore id
and our query is complete
then once this field has been updated
we're going to receive the results as
how many fields has been updated from
sqlize
we're going to
redirect
the user to
view the lead so we're going to use
slash lead slash
plus
rec
params
lead underscore id
so this way after the post is successful
and update is done we're going to be
redirected to
this route that shows the details of the
lead
now let's save our controller
and
run our application
and see how it works so i'm going to
open up the terminal the application
seems to be running ok
and i'm going to open up the browser
and browse to localhost 3000
let's create a new lead hello at
getbuzz.io and submit that so we have a
collection of leads displayed
let's click on one of them
and click edit we're now on the edit
route and i'm going to
shorten this
to let's say a at b.com
and save it
and i'm redirected to the show lead
route that shows the updated leads so
this concludes our tutorial on editing
and updating leads now is the time to go
back to our terminal and check in the
changes we made so i'm going to
type git add
views git add
controllers git add routes these are the
directories that we modified and then
we're going to comment
add
lead edit and post routes
the next route we're going to implement
is the delete route let's go back to our
editor routes slash index.js and create
a new route
router.post
slash lead slash lead id
slash we're going to use the delete path
components and then let's define
a new handler called delete underscore
lead
let's save this file and then go to
controller
landing.js and let's create a new
handler for the delete action let's call
this delete lead we're going to delete
the row in the database representing
this lead so we're going to type return
models
lead
destroy
where
id is rec
params.lead underscore id
then
redirect back to the
landing page
because we are going to delete the
current lead and everything associated
with it including
the page that shows the lead so
let's type rest.redirect
slash leads
now let's save this file so let's go to
[Music]
views
lead
lead.pug
let's define a new action here we're
going to use a button instead of a link
because the default method for accessing
a link is a get request but we're
interested in doing a post request
so i'm going to define a form here
action
will be slash
lead
slash
lead.id slash
delete
and method will be
post
we're going to have a button
of type equals
submit and we're going to
call the button
delete let's also
create some spacing
and we're now ready to run our
application let's go back to our
terminal the application is running
let's make sure we've saved all the
files
and try
let's go to slash leads let's
go to the details of the first one we do
have a delete button
now let's click on it
the entry was deleted let's try it again
okay this one was also deleted let's
take a look at our database activity
we're deleting from leads where id is
this id
this concludes our implementation of the
delete routes as usual let's check in
the changes we made i'm going to do git
add controllers git add routes we hit
add views we need comments
implement
delete route for leads
in this tutorial we're going to learn
how to implement ajax requests and get
started with using javascript in the
browser we're going to implement the
delete lead functionality
using client-side javascript so let's
start by defining our routes with
router.post
slash lead slash
lead id
delete and we're going to name this as
delete json
and we're going to define a new handler
delete lead json let's save this file
and go to controllers landing.js
we're going to copy
the delete lead handler we created
previously
and we're going to name it as delete
lead underscore json we're still going
to destroy a lead using the request
parameter lead id but then after that
instead of redirecting to the slash
leads route we're going to send back a
json object and we will do that by
typing res.send
defining a key msg
with the value success
now let's save this file and go to view
slash landing.pug
we're going to implement a button that
will invoke the ajax request that will
delete the particular lead
so let's
define a button
with the text delete and we're going to
define the on click property of the
button to call the javascript function
delete lead
onclick is an event that gets fired in
the browser when this button is pressed
and by assigning it that handler we make
sure that when the button is clicked
this javascript function will get called
now when we insert inline javascript
like this inside pug
we surround it with this character
called the grave accent which looks like
this
tilted single quotes
we're also interested in passing this
lead.id field to
the delete lead function but also we
want pug to evaluate the value of it and
pass the value and in order to do that
we type
dollar and then curly braces
id
and we surround the result with
single quote character
now i know this syntax looks a little
bit complicated but this is the best way
to add inline javascript in pug also
passing variables that need to be
evaluated for those who are curious
grave accent is this left tilted single
quote
now for the implementation of delete
lead we're going to use the jquery
javascript library so i'm going to
include that at the bottom of the html
page with this single line we're also
going to add
a javascript file that we are going to
define
as
javascripts slash leads.js so let's save
this file and go to javascript
leads.js
now let's define our delete lead method
and go over the details this delete lead
function is making an ajax call ajax
allows us to make http requests to our
web server using javascript also sending
and receiving data in form of json
objects
the key point with ajax is that the
requests the web requests happen in the
background while you're on the same web
page so if you go back to our browser
let's assume that i clicked on this
delete button and it invoked our
function that makes the ajax call that
means that we're still going to be on
the same page and then this url here is
not going to change and the request to
our web server and the response will
happen in the background now let's take
a look at the parameters we passed to
this function the url field defines the
route that we're going to call
and notice how this path matches the
route that we've defined for this
purpose
we have a data type as
json and then we typically pass the data
payload in this data field and
json.stringify function is
called to pack the data into a form
that's transmittable over the network
and then it gets unpacked on the other
side using another call that matches
this which is json.parse
the type of our request is a post
request and then we define two functions
one for the success case and one for the
error case and these get called when we
receive a response from the server
when we delete the lead from our
database using the ajax call we want to
reflect that the lead is removed to our
user on the browser window as well
now recall that we did not navigate from
the current url and the ajax call
happened in the background
for that reason we need to modify the
currently served html page we're
displaying in the browser
we do this dynamically in javascript and
delete the html that corresponds to the
lead that we've deleted
the currently served html document
visible in the browser is shortly called
as dom which stands for document object
model
now jquery has convenience functions
that help us manipulate the dom such as
this remove call
in this first part here we're looking
for an html element with the id of lead
id and then we're making a call to
remove to remove it from the currently
shown html document
now in order for this to work we need to
assign the lead id to the particular
html element we want to delete so for
that let's go to views slash landing.pug
to this paragraph element
for each paragraph we create for an
individual lead we're going to assign it
the corresponding lead id
now html documents are hierarchical and
what that means is that this paragraph
is a parent of all of these children
that have been nested inside it so if we
delete this paragraph element from the
html document that effectively means
that we're also deleting all the
children which includes all the details
for that individual lead so we're going
to
delete this whole thing by simply
searching for the paragraph elements
with the
lead id and then remove it from the html
document and that's effectively what
this call is doing
now a few useful details about jquery
when you see a dollar sign like this
it means that we're making a call to
jquery it just means we're making a
library call dollar.ajax means we're
calling jquery ajax and this dollar and
then the parentheses mean whatever
that's inside is going to be handled by
jquery the second detail i want to
mention is this part here
when you use this hash character it
means that you're simply searching for
an id
in the
current html document the dom
when we do hash plus lead id it means
we're searching for the elements with
that particular lead id jquery will go
and search for every element that has an
id property defined
which is a fast way of searching for
elements in an html document
now let's take a look at how our
application works let's go to the slash
leads route in our browser and click on
the delete button on some of these leads
as you can see the leads are being
deleted from this current html page but
let's see what happens in the background
so i'm going to open up the javascript
console
to see if you're getting results
so if i open up these result objects i
see that the message success has been
received from our server each time i
delete an object let's try it once more
and also let's take a look at what
happened on our server side
as we are seeing we're doing a post
request to the delete json route and
also we're able to delete leads from our
database
let's check in the changes we made i'm
going to do git add controllers
hit add routes
git add views we'll also define a new
javascript file so i'm going to do git
add public javascripts
let's commit this
implement
lead delete route using ajax
in this tutorial we're going to update
the looks of our application using the
bootstrap css framework so let's open up
our browser and search for bootstrap
and click on this link and go to
getbootstrap.com the easiest way to
include bootstrap in our project is to
include hosted cdn links of the library
in our project files
cdn shortly stands for content
distribution network and there are
third-party hosts for javascript
libraries and we will copy and include
the links for bootstrap library in our
project for that let's go to this link
and click on the latest version
and click on download and if we scroll
below
we're going to be given the links to the
bootstrap cdn let's copy and paste them
in our projects
there are also dependencies provided so
let's copy and paste them as well
now in this tutorial we're also going to
learn how to separate our pug files into
reusable components and we're going to
create a header a navbar and a footer
component that we can use across all of
our files let's create a new folder
under views called common
and let's create new files head.pug
footer.pug
and navbar.pug
let's go to head.pug and type mixin head
title
indent head
meta
char set equals utf-8 and
title equals title pug mixins allow us
to define common snippets and include
them in multiple pug files we can also
pass them parameters such as this title
field that gets used as the title of the
document let's go back to where we
copied the bootstrap stylesheet link
cut it and paste it on head.pug
and change the syntax to pug which is
link open parentheses some properties
and then close parentheses
we also need to add some standard meta
tags in our head section so let's do
that as well
now let's save this file and go to
footer.pug and type mixin footer footer
for the time being we're just going to
include the javascript files so let's go
back to where we copied the bootstrap
javascript files cut and paste them on
this file
we're going to change each script tag
syntax to use the pug syntax which is
script and then
open parentheses some properties and
close parentheses
let's do this one as well
now the order that these libraries are
declared matter and bootstrap depends on
these other libraries so they need to be
declared before the bootstrap
declaration so let's go ahead and fix
that order
we're now ready to include our header
and footer in landing that box so let's
go there and delete these first few
lines and type
doctype
html
blank equals
en
and we're now going to include
common head.pug and we're going to
invoke the mixin by typing head
and let's give it a title starter mvp we
need to add a body tag
and let's indent everything
to nest in the body
and then at the bottom
just before leads.js which depends on
jquery i'm going to add the footer
include
common
footer.pug
and invoke the footer mixing
and we don't need this line anymore
because we've declared jquery in
footer.pug
now let's save this file and reload our
landing page
we can see now that this is a bootstrap
enabled page now the page elements look
rather plain because we didn't add any
styling yet let's conclude our tutorial
by doing some maintenance work the other
pug file that we used was lead.pug so
let's do the same thing on that file as
well we're going to
copy and paste
this header section
we're going to add a body
we're going to indent the body to nest
it under the body elements
and we're going to copy the footer
section
to be nested inside the body and save it
we also are not going to make use of
this layout.pug file anymore so we can
delete that
let's check in all the changes we made
i'm going to type git add views common
git add
views
and hit comment
add a
common
header and footer section
in all pug files
in this tutorial we're going to focus on
the user interface and update the looks
of our landing page using bootstrap
templates let's open up our editor and
go to view slash landing.pug now under
the body i'm going to copy and paste a
bootstrap navbar example that i've
prepared earlier this is our navigation
bar typically for a functional component
of a page like this such as a nav bar we
can take a look at an example on the
bootstrap website and copy
now when we define components in pug the
first element you define is the html
element and then everything that comes
after that separated by a dot are css
classes css classes modify the
appearance of your html elements so in
this navigation bar we're first defining
a link and then we're nesting an image
in it which is going to serve as our
logo and then we have two navigation
links nested in an unordered list notice
how each html elements has a different
css class these are classes defined by
the bootstrap framework and available to
us one last point here notice how we
define these html elements in pug but
this line does not contain a beginning
html element and that's because this is
typically considered to be a div you can
type it like this or you can omit it and
it will be assumed that the first
element is a div element we're also
making use of an image asset file for
that i copied the file under public
slash images slash file name all your
assets which are shortly static files
that never change in your application
are stored under public you can refer to
an asset file in html by starting with a
slash and then the folder name and then
the file name so as the root of your
asset path slash refers to your public
directory
let's try and run our application by
reloading our home page
now we see a navigation bar two links
and a logo
now as we did previously i'm going to
cut this nav bar from here and place it
in a common mixing file so let's go
under views slash command slash
navbar.pug we created earlier and paste
this code we're going to define a new
mixin called navbar and currently we're
not needing any arguments and i need to
indent this by one level under mixing
and save the file now let's go back to
landing.pug and include our mixin under
body we first need to add a header tag
include
common slash
navbar.pug and then plus navbar
and let's update the rest of our page
using bootstrap html elements i'm going
to type container
and we create a new row and then inside
the row we create a new column
and the size of that is six for a medium
sized screen we're going to copy and
paste a header and a paragraph or two
for our value proposition and let's
delete these two lines here
there were a few css classes that
were previously
prepared i'm going to copy and paste
those
and we have a form snippet as well that
matches the form we created before
copy this portion
the contents of the
input element
and let's delete this part
now let's save this file and reload our
page
now we have a landing page that has an
updated look let's go back to
landing.pug and we're going to update
the portion where we list the set of
leads
for that i'm going to create a new row
and then a column with an md-6 type
we're going to indent this portion
and i'm going to replace this portion
with a table let's go ahead and do that
now if we reiterate on this source code
if
there is a variable called leads we're
showing the title leads and then we
start a table
inside the table under this t-head
elements
we list the names of the columns for the
table we're using the name email for the
email field and then the actions under
the t-body tag we're listing the rows
for the leads so here for each lead in
leads we're creating a new row and then
we're listing the email for the lead and
then a link to the details also the
delete button for it
notice how we move the lead id as the id
property to the table row so that the
delete lead call can find which row of
the table to delete when it's deleting
the lead
so as a recap if you go under public
javascript leads.js
this line will find the right html
element and then remove it
and
in the case of a table this is the table
row
you can check out the bootstrap
documentation on how to build tables
like this now i want to make a few fixes
on the indentation under this h1 tag we
are nesting this table and that's not
correct so i'm just going to de-nest it
by one level also we want to nest this
row under the container tag so let's go
ahead and do that
that's done let's save this
now a few more changes let's go to
navbar.pug
i want to update the link to the leads
route
and also let's go to footer.pug remember
when adding a dependency for the
bootstrap library we added this jquery
3.3.1 and then the slim version turns
out the slim version does not have ajax
calls so we won't be able to make the
ajax call under this delete lead
function so i'm going to go back to this
and delete this slim portion so we're
now referring to the full version of
jquery that includes the ajax calls as
well we need to delete this integrity
hash as well since this was referring to
the previous file let's save this
and we should now be ready to run our
application let's go to our browser and
reload the home page and let's click on
the leads link and if we go down below
we see all the leads listed and let's
click one of the delete buttons to
delete them before we move on let's
check in all the changes we made so i'm
going to do git add
views
common
git add views
landing
dot pug
and let's try doing git comments
and let's type install
bootstrap
and update the look of pages
while we're at it i want to organize our
pages under the lead directory and i
want to remove the list of leads from
the landing page and create a dedicated
page for leads so let's go under lead
and create a new file and save it as
leads.pug we're going to copy the first
portion of our landing page let's just
copy
this part
and paste it here also
let's copy the footer part
and paste that as well
and in this middle section we're going
to
create a new container and then a column
let's copy and paste those these are
nested under body and header
and let's
cut and paste
the section for
leads we're actually not going to use
these
two lines in the landing page either so
let's delete those save it and under
leads i'm going to paste the section we
don't need this if leads check because
we're already displaying a page
and let's save this file now let's go to
controllers landing.js once we submit a
lead we're redirected to the
leads route and once we show the leads
instead of using the landing page we're
going to use the new page we defined
and that'll be under
lead slash leads
let's save this file and let's go ahead
and run our application again
if i reload this page i got an error
because the
head file is located under common and i
am one directory level below with the
leads.pug file so i need to type dot dot
slash for all the common files
let's save this file and reload
our application again
and here we are on the leads page we can
now see the leads on a separate web page
let's also update the title here to
leads and i'm also going to move this
lead.pug file under the lead directory
so let's just do that
move
use lead.pug views
lead need the pug
and i'm also going to update the css
classes here to match the ones we use
under leads and to use bootstrap so
let's copy and paste the code we have
for leads.pug
into lead.pug
and let's take the section that lists
the single lead
and let's delete the rest
assuming that we are going to use a
table
we can update the contents of the table
to match a single lead
so instead of having for lead in leads
we're just going to access the lead we
have let's
do this the first field is the email
field which is the same here we can
change this as edit and then delete and
here we're going to
have
edit
plus slash edit and instead of the ajax
call we were going to use this form
let's copy and paste that
and as you might know we're using the
button
using the
bootstrap css classes so let's double
check what we're doing the first entry
is lead.email and the second entry is
the link to slash lead slash lead id and
then edit which matches the link we
created here and then the last one is a
http post when we submit with this
button
and the path is slashly lead id delete
so let's delete this portion
and the body let's save this file
and let's go to
controllers landing.js when we render
the lead page that is now located under
lead
lead let's save this
and run our application again so i'm
going to go to the browser window if i
click on the details
now
i am seeing the lead page it now has the
bootstrap classes and a table we need to
redo the same exercise with edit
lead.pug although i'm going to copy and
paste code i prepared earlier because
it's repeating the same exercise so
let's delete this html and
paste
this concludes this part of our tutorial
we've migrated all of our pages to
bootstrap and also creates the separate
leads view file
let's check in our changes
in this tutorial we're going to develop
sign up and login functionality and
learn how it all works let's open up our
editor and open route index.js we're
going to get started by defining the
routes for login and sign up so let's
type router get slash login we're going
to use a new controller called user and
we're going to use a handler called show
login to show the login page and then
we're going to have a router.get for
signup
and again we're going to use the user
controller and type show
sign up now let's define our user
controller here as well
so i'm assuming we're going to define
a controller called user under
controllers and let's save this file and
let's go to controllers create a new
file called
user.js
i'm going to copy and paste code that i
prepared earlier nothing much happening
here we're simply showing the
login page the view is located under
user slash login and then we're showing
the sign up page with a sign up view
under user directory we're also passing
two objects to the
view file
one is form data and the other one is
errors we're going to get back to these
later on for now let's know that we're
simply passing empty objects because
these views are located under the user
directory let's go ahead under views and
create a new folder called
user and i'm going to create two new
files called
login.pug
and
signup.pug
now let's define these pages i'm going
to paste some code that i prepared
earlier for this nothing much
interesting happening here since we
covered bootstrap a little bit before
but the essence of this page is that we
have a form that posts to the signup
routes and we're placing two input
elements here one is an email and the
other is a password and we're submitting
them with the submit button and then we
have a link at the bottom for the option
of going to the login route now let's go
to
login.pug also i'm going to paste code
that i prepared for this it's
essentially the same code except we're
posting to the login route and we're
passing an email and password field
as well and the purpose of this page is
to log in and then we have two optional
links at the bottom one is to reset a
password we haven't got a route for that
yet and then we can go back to the
signup route let's save these files
and go to our browser to take a look at
how they work so this is how our login
page looks and if i click on the signup
route this is going to serve as our
signup page now is a good time to define
our user model and migration of our
database so let's go to models and
create a new file called user.js
since we covered one model definition in
detail for lead js before i'm going to
paste code that i prepared earlier for
the user model definition and let's go
over it quickly so we're defining a new
user model
we're defining an id and then we have
several fields of type a string we have
a username first name last name password
and email now we're not going to make
use of these first three fields so we're
passing a property along null true so
that we can create rows that have null
values for these fields and we're
essentially going to make use of the
password field and the email field and
we're also passing the property unique
for email as a constraint so that each
unique user is distinguished by his or
her email address and email is a
candidate key for this table now we need
to create a database migration that
matches this model so let's go to
migrations and create a new file and i'm
going to name this file
with today's date
so that it goes in the right order in
terms of migrations and comes after the
lead table migration let's save this
file
i'm also going to copy and paste codes
to go
faster since we've covered a migration
example before
so as we covered previously the
migrations have two methods one is an up
method to to
move the table
definitions into a new form and then a
down method that rolls back the change
that's being made in this migration
we're creating a new table called users
and the fields we're creating match the
fields we defined in the model nothing
surprising or interesting here let's
save this file
and go to our command line to run this
migration i'm going to type
sqlize
db
migrate
our migration has succeeded so we have
created this table in our database and
before we move on let's check in the
changes we made so i'm going to type git
add views user git add controllers
hit add routes and git commit
implement get route for login and sign
up
we're also going to check in the
migrations and models so for that let's
do git add models
and git add migrations
and git commits
create
user model and migration
now let's open up our editor and go to
routes slash index.js and we're going to
define the post routes for login and
sign up so let's type router.post
slash login user.login router.post
signup
user.signup
now before we move on let's define these
controller handlers as well so let's go
to controllers users.js
and create these two empty handlers sign
up and login
now we're going to implement the sign up
and login routes using a node.js library
called passport.js in particular
passport.js helps us with implementing
authentication as you might guess
there are many ways to authenticate your
users you could use social networks or
other means multiple methods of
authentication for us and if you're
interested to find out more you can go
to passportjs.org for more details
now let's go back to our terminal to
install the packages we need let's type
npm install
passport we're going to use an add-on to
passport for local authentication to our
database so for that let's type
passport-local we're going to use a
library called bcrypt for encrypting our
password
and we're going to use the package
validator to validate the input we make
on login and signup routes we're also
going to need to create sessions for our
users so let's
type express session and finally we're
going to display error messages if login
or signup fails for any reason and for
that we're going to use a package called
connect dash flash so let's
type dash save and press enter
this might take a while because we're
installing multiple packages
and let's check in the changes we made
so i'm going to type git add
package.json git add
package lock.json and comment
express session and connect flash
now let's go back to our editor we're
going to go to app.js to create an
instance of passport so let's type let
passport equals require
passport we're also going to define the
session so let
session object equals
require express
session
and let's go down below right after this
line we're going to declare app dot use
session
we need to define a secret parameter for
this let's just type our new secret for
now and in the second line we're going
to type app.use passport.initialize
and finally app.use
passport.session
now each of these calls must be in this
given order otherwise your application
may not work because when app.js is
processed it goes line by line to
configure the app instance in a
sequential order so that's why we need
these three lines in this order
now we're interested in setting up
passport in a separate file than app.js
in order not to clutter app.js with
details of passport.js setup so for that
before we create the app instance we're
going to add one more line here we're
going to type require
dot slash passport setup and we're going
to pass the passport object now let's
save this file and create a separate
file in our root directory called
passport underscore setup.js and save
now in passport setup.js we're going to
start by defining an empty function
that we're exporting from this file
and we're passing the passport object to
it as you might see here we're also
calling the same function with this
require statement and we're passing the
passport instance we created a few lines
earlier so let's go back to
passport.setup now passport.js requires
us to define a few well-defined api
calls to function properly
the first function is called serialize
user and the second one is called this
serialize user this stackoverflow page
explains it quite well serialize user is
used by passport.js to save a handle to
the user object
in this case it's the database id for
the user
it stands saved to a session variable
and later on the serialized user will
use this handle to retrieve the actual
database object for the user
user object is then assigned to the user
key of the request object so that we can
use it in our controllers or routes so
let's go back to passport setup.js and
define these functions
for serialized user we're going to
simply use the
database id
and for the serialized user we're going
to query our database
we'll pass the id to our user and then
we're going to type
models user find one
where
id is the id parameter
and then
we get the user object back
if user is null
it means
there's an error so we're going to throw
on error object
wrong user id
and else we're going to call done null
user with the user object
so we're almost done as a recap
serialize user function determines which
handle to the user object is to be saved
in the session and then the serialized
user will retrieve the user object using
that handle
now we need to define a strategy for
passport.js to use to authenticate our
users when they log into the application
because we're going to use email and
password as the method for
authentication we're going to define
what is known as a local strategy for
passport to authenticate our users via
email and password now let's go ahead
and type
let
local strategy
equals require
passport local this is where this
package comes into play and then we're
going to type strategy
now we need to tell passport.js that we
will be using the local strategy for
authentication for that we add a
statement passport.use
new local strategy
local strategy will call its
authentication function when there is a
login form submitted via a post request
so local strategy needs to know which
fields in the submission contain the
username and password for that there are
two optional fields to define these
username fields in our case it is called
email
and password field
and in our case it is called password
now if you go to login.pug you will see
that the first input field is named as
email which we will use as the username
and the second one is named as password
so when the local strategy accesses
request body email it will consider that
as the username and then when it
accesses
request body password it will assume
that to be the password field now we
need to define an authentication
function where we access the database
and show that there is indeed a user
with this email address and the password
provided we type function
email
password and done
now this function will authenticate the
parameters however we also need the
request object here and in order for
passport to pass us the request object
as the first parameter we need to give
it another option called
passwreck
call back
true we're going to use this for error
handling later on
now let's define our function
let's open our curly braces and type
return models user find one
where
the email field is the
email parameter and
then we will receive a result which
let's call
as user and if this user
is null
it means we couldn't find the user so
we're going to return an error
message
incorrect
credentials
and we need to add
return done null
false
and we're going to type else if
user.password is null or
user that password
is
undefined
rec
flash
message
you must reset your password
these wreck flash messages will be shown
in the subsequent re-render of the page
and we're also going to type return done
null false this is another error case
finally else if we're going to define a
function that validates the password
provided is correct so let's call that
valid password we're going to define it
shortly
we're going to pass the user object and
then the password provided in the login
form
and let's type rec
flash
message
incorrect
credentials and this will be entered if
the password isn't valid so i'm going to
add a not and here we're going to type
return
done null
false so we have handled all the error
cases and if we have a valid user we're
going to return done
null
user
there may be further errors other than
incorrect credentials being provided and
we will handle them with this
catch statement in the end for example
if there was a database error when
accessing the user model that will be
caught by the statement so we're going
to type catch
error
and done
error false
now let's save this and let's go ahead
and define the valid password function
for password validation we need bcrypt
library so let's type require decrypt
actually for accessing the models the
database we also need to define the
models variable
by typing require dot slash models
and we're going to compare the past
password versus the one in the database
so let's type
valid password
equals function user password and then
return bcrypt
compare sync is a decrypt function we
will pass
the password in the login form versus
the user.password field
now the passwords contained in our
database is a hash of the provided
password so that we don't keep them as
clear text so this function will also
convert the password to a hash and
compare the hash value to the one that's
being stored in the database this way if
the database was compromised the
adversaries cannot access the clear text
passwords but they only get access to
the encrypted versions we're done with
the implementation of our first passport
login and signup strategy using the
local strategy and let's go over the api
calls again so we're providing passport
with a handle to the user object which
is to be saved in this session and then
passport.js will use this handle to get
the actual user object from the database
we also define a local strategy where we
tell passport.js what fields to use for
the email and password fields when
authenticating the user post request
during authentication there may be
various errors once the database is
queried given the email and password
fields there may be multiple
authentication error cases one of them
is that the incorrect username is
provided the password field is not
present or the password is simply not
valid in such cases we return an
authentication failed message back to
the user
in the successful case we pass the user
object to the done callback and we also
catch database or other internal server
errors with a catch statement
we use a valid password function call to
compare the past clear text password
with the hash that's stored in the
database we're now ready to check in our
changes so let's go back to our terminal
and type git add app.js
git add
passport setup js and git commit a
implement
passport local
alt strategy
using email and
password fields
now that we have set up passport.js we
can go ahead and use it in our sign up
and login route so let's go and open up
controller slash user.js in the signup
handler we're going to create a new user
by using the user model and then save it
to our database so let's type
const new user equals
models dot user.build
email
rec body email and password we're going
to use a function to generate the hash
of the password so let's call this
function
generate
hash
and we're going to pass rec body
password
once we build the user object
we're going to save it by typing return
new user dot save and this is a promise
so we're going to do then results
and inside the body of this promise
we're going to make a call to
passport.js to authenticate the user
after signup so let's call passport
authenticate local since we are using
the local strategy and then we're going
to define a redirect route after the
authentication so let's type
success redirect
slash
failure redirect which is used upon the
passport authenticate call failing we
will call slash sign up and we're going
to define a flash message failure flash
true we're also going to pass the
request response and next objects
now in order to use the models object we
need to first define let's models equals
require
dot dot models
and let's define the generate hash
function
const
generate hash
equals
function
password
and in the body we're going to use the
bcrypt method hash sync so
return
be crypt
sync
decrypt
can salt
sync
8
and null
so generate hash function will take the
password and create a salted password
what that means is we're going to create
a hash of this password and save the
hash in the database now let's also
define the decrypt object let's be crypt
equals require bcrypt
let's also define passport
equals require
passport we also need to set up passport
so let's type const
my passport equals require dot dot
passport setup
and we're passing the passport instance
we also will need flash so let's type
let flash equals require
connect flash you might be wondering
what's flash stands for flash allows us
to display an error message on the page
that's going to be rendered so it's a
one-time message that we can send to our
clients
now let's save this file and run our
application and verify that
the signup works i'm going to run the
application go back to the browser and
type slash sign up
let's type user at email.com and then a
password and press sign up
now that we've been redirected to the
slash route it seems to be working let's
go and verify this by going to our
terminal
here we're inserting a new user to the
database with the email that i have just
typed we have also started a new session
with our application
now let's go back to our editor and
implement the login route in login route
we authenticate a user and initiate a
session with our application
for that we're going to do the identical
action as we did in sign up with
passport so i'm going to copy and paste
that code
the only difference being here is that
upon failure we're going to be
redirected to the login route
let's check the result by going back to
our browser
and let's type slash login
let's type
user at email.com and then the password
and i'm going to click on login
and i'm redirected to the slash route
which means the login was successful as
well and i've initiated a session with
my application
now let's go back to our editor
routes slash index.js and for
completeness we're also going to define
a logout route
so let's type router.post
slash logout
user.logout
and router.get
logout
user.logout
for both requests we're going to use the
same method
now let's go back to controller's
user.js and define a new method
called logout
we can destroy our session by making a
call to rec
logout
and rec
session dot destroy
and we will then redirect the user with
rest.redirect
back to the root route
now it will help us to display these
routes as links in our navigation bar
also we want to know whether we have a
user session or not so let's go to views
slash navbar.pug to implement this
i'm going to paste the snippet that i
prepared earlier
here if we are passed a user variable
that means we have an active session
going on and we display that by showing
hello user email on the navbar we also
have links to logouts login and signup
routes
now for this user variable to be passed
we need to define it as an input to the
navbar mixin so let's type user and save
this file
and navbar is used from the landing page
so let's go to view slash landing.pug
and pass the user variable to the navbar
mixin
let's save this file and now let's go to
controllers slash landing.js
we're going to pass the user variable to
the render function so let's type user
rec dot user
if you recall passport.js will populate
this rec.user field with the user object
if there is an active session going on
let's go to our browser window to test
the login and logout routes
let's go to login and type
user ads
email.com password and login
as you can see we have logged in and we
can see the user information here
and let's click on log out
and now the user session is destroyed so
we don't see the user email address here
anymore
now let's go back to our terminal and
check in all the changes we made if we
type git commit dash a it will include
all the files that have been modified
let's type implemented
sign up login and logout routes
using
passport.js
in this tutorial we're going to learn
how to validate form input when a form
is posted to our server and how to
re-render the page with error messages
when there are errors
as a recap for how we handle form
submissions let's open up our editor and
go to routes
index.js
here we have defined a post request
handler for sign up path using this
user.signup handler so let's open up
that handler by going to controller
slash user.js
if we look at the signup post handler we
see that we create a new user object
without validating the input we receive
from the form reg body email and recbody
password fields are used directly to
create the user and save to the database
we're going to change that and validate
these input fields first before saving
the data and for that we're going to
define a validator function for our form
input so let's get started by installing
the validator package by typing npm
install
validator we are also going to use a
package called low dash so let's add
that as well and type dash dash save and
press enter
let's commit our package.json just in
case we made any changes so i'm going to
type git commit
package.json and package log.json
okay
install validator and lodash
now let's go back to our editor and in
the root directory my app let's create a
new folder called
validators and save that
and we're going to create a new file
called
signup.js here let's type let validator
equals require
validator
save that
and i'm going to create a local function
called validate create user fields
function this is going to receive an
errors object that is empty and we will
populate it as we find errors in each
form input field
and we're going to receive the form
input fields with the rec parameter
which is the request object so let's
type if
validator
is email
rec body
email here this mark stands for not so
if this input is not an email then
we will populate the
errors object with the key email with a
message please use a valid email so
we're going to go over each input field
like this with an if statement so the
next one for us is if
not
validator
is ascii we're requiring that we want
the password to be made out of ascii
characters and we're going to pass the
password with rec.body.password
if this doesn't hold true then we're
going to populate the errors object with
the password key to be
invalid characters in password
please try another one
we also want to enforce a password
length so let's type if not
validator is length track body password
here we pass a length range object with
minimum of 8 characters and maximum of
25 then again we're going to populate
the errors for the password key
please ensure that your password has a
minimum of 8 characters
now we're done with this function
because the errors object was passed
into this function it will be modified
in place so we do not need to return the
errors object
now other than this basic string
validation we need to make sure that
there isn't an existing user but the
same email as the address provided in
this email form field for that we need
to query the database so let's define a
wrapper function export
validate user
function pairs rec
let's type return
models user find one
where
email is wreck body email
and then
we are going to get value u
if
u is not equal to
null
then
we're going to populate the email key of
the errors object email is already in
use please login or reset your password
now i need to introduce you a new
concept on program execution
when we define the body for validate
user where we query the database this is
an asynchronous piece of code so it will
execute sometime in the future and we
will get the results also sometime in
the future
and this first portion we defined the
validate create user fields function is
a synchronous piece of code which means
each of these statements will execute
sequentially
now in order to validate the form fields
we need both this function which is
synchronous and this function which is
asynchronous
and we need to mix the two together
for that we need to use a concept called
promise and make the entire body
asynchronous we're going to cover
promises in the future in more detail
but for the time being what you should
know as a recap is that this piece of
code is asynchronous and this piece is
synchronous and in order to make use of
both in a single function we need to
define a promise which wraps the entire
code in an asynchronous body so for that
let's type
return new
promise
function
resolve
reject
and we're going to create the promise
body let's cut this piece paste it here
and indent it inside the promise and
let's make a call to validate
create user fields errors rec
and we will return the errors variable
in resolve
errors
and let's not forget to include the
models variable so let's go to the top
and type let models equals require dot
dot slash models now let's save this
file
now let's go back to controller slash
user.js and import validate user so
let's type const
validate user equals
require
dot dot validators slash signup
now let's go down to the signup handler
and declare a new variable let errors
equals an empty object and we're going
to call return
validate user
errors and we're going to pass the rec
object that contains the input fields to
be validated so let's move on and type
then
errors which is going to be the result
we get from validate user
and we're going to check whether the
errors variable is populated with any
values so let's type if
not
is empty errors which means
the errors object has some values we're
going to
call a new method
rerender sign up
and we will re-render the form just as
we will render the form for the first
time using the show sign-up ender except
we're going to display the error
messages that we have populated during
the validate user call
so let's add the errors variable here
errors and we're also going to pass the
usual wreck res and next objects now
this case covers the case where we have
errors on the form and we will handle
this successful case here as well so
let's type else and inside the else body
let's cut and paste rest of the code
and let's indent it
so this means if there is an error we're
going to re-render the form and if not
we're going to save the data to the
database
there's one more thing we forgot this is
empty function is a call that's been
provided by the law dash library we just
installed so we need to type
const is
empty
equals require
low dash
now is a good time to define our
rerender signup function it's going to
be identical to show sign up with a few
differences so let's copy and paste show
sign up and we're going to make this a
local function so let's type const re
render sign up
now even though re-render sign up looks
like a request handler such as show sign
up it's actually just a function call so
we're free to modify its function
signature with the order of parameters
being passed normally in express.js the
request handlers have a particular order
in their parameters in particular the
request response and next objects are
passed in that order
so
we render sign up is called from the
sign up handler at this point
and we can pass the errors object as its
first parameter and we're then going to
pass that to the errors key so that
errors can be displayed on the form when
the page is re-rendered
we also have another field called form
data and form data is a name that we
made up in particular for
when there are errors on a form when we
re-render that page we use
form data to pass back all the input
fields that have been modified by the
user
so that let's say when there are errors
the user does not have to re-enter the
same information to the other form
fields again and again on each time the
form is re-rendered so we save the user
a time by passing back
the data that's been entered already in
a previous submission so in order to
pass that data back to form data key
we are going to use rec dot body if you
recall if we go down to the sign up
handler
when the form is submitted to us we have
all the form input fields available to
us in rec.body object with the keys
corresponding to the input names such as
email and password so by passing back
rec.body after the submission
we are effectively passing back all the
input fields that have been
submitted to us on the form submission
so we're passing rec.body back in form
of the key form data
now if you recall show sign up is using
user slash sign up view and we're using
the same
view in re-render sign up as well so
we're going to modify the sign up view
to cater for both cases of the showing
the form for the first time and also
re-rendering the form with errors and
existing form information
so let's go ahead and open up views
slash
user slash signup.pug to modify it and
to use form data and errors fields
now let's take a look at the first input
field with the name email
we can pass back existing values on an
input field using the value property so
here for the value property we're going
to type form data dot email we could
potentially populate the value property
of the password field as well but we're
not going to do that as password is a
sensitive field so let's add error
message information now and let's create
a new line under the first input and
let's type if errors
and
errors dot email which is the name for
the input field
we're going to type p dot small dot text
danger these are classes from bootstrap
and we're going to finally display the
error message errors.email
if you recall we create these messages
in the validator function let's do the
same for the password field so i'm going
to create a new line under the password
input field and let's type if errors and
then
errors dot password
p dot small dot text danger
errors.password
now let's save our file and we should be
ready to try what we've done so far now
let's go back to our browser window and
go to the slash signup routes
and i'm going to type user at
email.com we know that we have a user
already with this email address so let's
see what happens when we include that
and for the password i'm going to type
4 character password which should also
trigger an error so if i click on sign
up i do get the form re-rendered with
the right error messages notice how the
validator has both detected that the
email is already in use we've done this
with the database query and the password
length was also detected to be not valid
let's check in all the changes we made
it add
validators we've added a new directory
validators
and we've implemented
error handling and form validation for
sign up routes
in this tutorial we're going to learn
how to implement access control in our
application also we will learn the
concept of a middleware and how to use
it in express.js
the problem with our application in its
current form is that the leads link here
is open to public anybody can click on
this link view our links or edit them
and we're going to fix that so let's
open up our editor and go to routes
slash index.js
in express.js a significant property of
route definitions is that we can
introduce a sequence or a chain of
function calls before we make a call to
the final handler for that route
let me show what i mean with an example
i'm going to introduce a new call right
after the path component called know
and place a comma and let's define north
with const no equals function
rec res next and an empty body
as you recall the handlers in express.js
have this particular function signature
where there is first a rec object and
then a res object and the next object
and we've never made use of this next
object here so we're going to make a
call to next
and leave it at that
what this does is that when the slash
leads path is matched the first function
to be called is going to be know
and no op will transfer execution to the
next one in line which is show leads and
the way we do that is by making a call
to next
i could potentially add additional know
up calls here
and it will be all the same because no
op does nothing but transfer the control
of execution to the next one in line in
a route definition we have the
capability to add as many calls as we
need to any
separate handlers before we call the
final handler and this gives us a lot of
flexibility for adding additional
functionality to each route and we're
going to see one example shortly
before we move on i want to demonstrate
you that these no op calls indeed have
no effect and we are able to call show
leads as normal so let's go to our
browser window and click on the leads
link
and we're still able to see the leads as
usual
now let's go back to our editor window
if you notice these knob calls are in
the middle when handling the request for
this route
that's why they're called middleware
middleware may sound like a grand term
that does something complex but a
middleware can merely be
a simple function call such as this knob
function
and let's remember that in a middleware
function we always need to make a call
to next in order to proceed the
execution to the next one in line and
make sure that the final handler gets
called
now we're going to define a really basic
middleware first let's delete the snob
call and delete these calls in the
middle
and let's create a new folder called
middleware in our root directory
and we're going to create a new file
called
has auth.js
let's type let create error equals
require
http errors create error function allows
us to create an error object with an
error message and we've already made use
of this in app.js and it comes as
standard with the vodila express.js
installation so let's go back
so let's define a new method exports is
logged in equals function rec
res
next
if
rec.user
then we will call next
the presence of rek.user means that
passport.js has authenticated the user
there's a session and there's a logged
in user who is requesting the page so
we're allowed to go to the next step of
handling that page and else we're going
to create the error
create error 404 and we're going to give
the message
page does not
exist now there's one thing i need to
mention about how this next works in the
successful case we're calling next to
move on to the next handler but in the
error case we're also calling next so
how come we're showing an error message
when we call next which should normally
call the next
handler for this route well the answer
is in the express documentation if you
pass anything to next function
express regards the current request as
being an error and it will skip any
remaining non-error handling routing and
middleware functions
what that means is we're going to skip
all the route handlers that are coming
next and we will go straight to our
error handler using the object we're
passing here and that error handler is
in app.js if you scroll down below you
will see this
error handler already defined for us
when we pass an object then that means
that this error variable will have that
object being passed from next and we're
going to display an error message and
render the error page
so that describes how next will work in
both cases of a success and error let's
save this file and go to index.js under
routes folder and we're going to import
this function we have just defined so
let's type let is logged in
equals require
dot dot middleware slash has auth.js
and we're going to use it's logged in in
the leads route as our middleware so
let's type is logged
in and then a comma let's save this file
and try our application again so i'm
logged out so and i'm going to reload
this page and i'm going to click on
leads let's see what happens
indeed our middleware has found that the
page does not exist and generated a 404
error
while we are at it i want to beautify
our error page as well so let's go back
to our editor and open up views slash
error.pug and i'm going to copy and
paste code that i prepared earlier for
this we're using a few bootstrap classes
let's save and reload this page
now this looks better
just to note we're able to see exactly
what happened in the application and
that's because the application is
running in debug mode if we were running
in the production mode we wouldn't see
this error stack
now just to demonstrate you the other
case let's go back to the landing page
and log in i'm going to type user at
email.com and sign in now if i click on
leads i'm able to still see the leads
now every user has access to our leads
table so we're going to take our access
control concept a little further and
only allow a particular user to have
access to these pages
so let's go back to our editor and
create a new migration under migrations
let's create a new file
with today's date
we're going to add a new field called is
admin to the users table i'm going to
copy and paste code that i prepared for
this earlier
and let's go over it quickly so what
we're doing here is creating an easy
admin field which is a boolean and when
it's true we will consider the user as
an admin of our application and here we
have the up method for the migration
where we add the column to our table and
the down method which will remove this
column from our table called users let's
save this file and go back to our
terminal and type
sqlize
db
migrate
so we've successfully migrated our table
and added an ease admin boolean field to
our users table now let's go back to our
editor i'm going to make a modification
in the way we create new users
let's go to controller slash user.js and
the signup handler
now if there are no users in our
application with an admin flag as true
we're going to create the next user as
an admin and for that i'm going to
modify the sign up handler
let's type
return
models
user
find one
where
is admin
is
true
then
user
and if
user exists
that means user not equal to null
then we're going to craft the user row
as normal so let's cut and paste
the way we create the first user
and else we're going to
create the user
with the field is admin equals true and
for this to work we need to
first declare
new user outside
use the new user variable and finally
we're going to save the user back to our
database so let's place this after the
else statement
let's save this file and
check that our application is running
correctly what we haven't done is update
our model under models with the is admin
field so let's create an is admin field
under here at the bottom i'm going to
copy and paste code that i prepared for
this earlier so ease admin is a boolean
and we allow it to be
null
because the existing users won't have
this field set let's save our model file
and go back to our browser and let's
sign up as a new user
and i'm going to type a password for
that and press sign up now we have admin
at email.com signed in and let's go back
to our terminal to verify that this user
was indeed created with is admin as true
insert into users
first second third and fourth field is
is admin and i can confirm that admin at
email.com is
confirmed as an admin in our application
now we're ready to implement the is
admin check in our middleware so let's
go back to our editor and go to
middleware has alt dot js
and i'm going to define a new function
here exports dot has auth
equals
function
request next
and if rec user is not null and and
rec user dot is admin
is true then we're going to call next as
usual and allow access and else we're
going to create an error as before next
create error 404
page does not exist let's save this and
let's go back to routes slash index.js
to import this new method as auth
and we're going to replace the is logged
in middleware with this one so let's
type as off and save this and open up
our browser and let's reload this page
and i have the leads link here if i
click on this link i'm still able to see
the leads and i'm going to log out now
and log in as another user that i just
signed up as which is no admin at
email.com
and login and if i now click on the
leads link i'm redirected to the page
does not exist error page so this
effectively demonstrates our use of the
has out middleware in order to control
access to certain pages on our
application we now want to extend this
to other routes where the leads are
edited and accessed so we're going to
add the has out middleware to other
routes as well so let's type has alt
for show lead
as out for the edit lead
and the rest
now all of our routes are protected by
the has out middleware except the first
one which is for visitors and the
landing page now let's check in our
changes let's type git add
middleware git add migrations git commit
a
and implement
has auth middleware
and is admin flag
lead routes are protected by as auth
and only the admin user has access to
them
i hope you enjoyed these tutorials my
name is bahadur i'm a systems software
engineer my background is in low level
software and operating systems if you
enjoy these tutorials and want to be
notified of similar content in the
future you can go to this website and
join our community here if you scroll
down below you will see a button to join
it's free thank you for watching these
tutorials and i hope to see you in
another tutorial in the future
you