Express.js & Node.js Course for Beginners - Full Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi in this tutorial I'm going to show you how to develop a web application using node.js and the expressjs web framework we will then deploy our application to AWS using elastic beanstalk 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 intermediates programming knowledge but no background in web application development or no js' okay let's get started so a little bit of background on node.js many years back developer Ryan dole explore 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 not Jas took Google's optimized 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 or managing the open source JavaScript libraries was introduced called NPM and nodejs was born now before we install node.js we're going to start by installing a script called nvm so go ahead and type env m in your browser and click on this link nvm is short for node version manager it's scripts 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 scripts for a VM and we'll paste it on our terminal now I already had an VN 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 in VM script can initialize while your terminal starts you can check that your installation was successful by typing in VM - - version we're now ready to install no js' or let's go back to node.js org we're interested in the long-term support version of node.js and as of this video it is ten-point 15.0 is the version that we need so we go back to our terminal and type NPM install 10 15.0 this step may take you a little bit longer you should have now no GS 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 dot 3 for example and you can switch between node.js versions by typing nvm i use so let's switch back to using node.js 10.15 dot 0 now for our application we're going to use Express J's so let's go ahead and visit Express J Escom expressjs 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 commands for expressjs but we're going to use another tool called the Express generator that will give us a good starting points and a directory structure so let's go ahead and copy and paste this command you know 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 useful directory structure so I'm going to copy paste this command here - - view equals pod means we're going to use Park as our HTML template in 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 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 our 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 web page or style sheets that describe the style on a web page the Ralphs 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 pyke files on each of them get converted to separate HTML page the bin the WW file contains the initialization script for our web server and one of the notable files is fjs this is the main entry point for our entire narrative application and also we have the package dot 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 fight 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 webpage served if we go back to our source code fjs is the most important file that we care about fjs defines our web application and node.js expressjs 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 Punk 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 we go up here we use the require statements to include an index j/s under the routes directory whatever that has been exported from this index.js file is assigned to an index route or variable and this instance is then used for the path that is slash so this line means that our application is going to use an index router for the slash route and that's how we also connect pieces of our application into one analytic instance because indexed router was defined here under index j s and it has been included from fjs let's take a look at how the routes object is defined if we go under routes index of joy yes 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 EPIP j/s includes that router here and that's how we connected and the router objects 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 - it only responds to the c-can't 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 route indexed Jas we're creating an Express instance and then recalling Express dot router to create a router instance and on this router were 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 dot j s we have indexed router representing our exports from routes slash index file and then we have this statement here app dot use and for the slash path we're using index router effectively meaning that when we type this route path with no / or / e 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 GS specific method called res not render the resident render will generate an HTML page and our web server will respond back to the browser request with a Paige 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 a post request it does something with the sent data such as updating a database and then the server typically calls the res that redirect method again this is specific to express J's 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 route angler 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 route anglers 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 dot J s and if I go back to the route defined in the 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 rod file so if I go back to controllers as a recap we have an index of Jas and we have a method called index that we're exporting as our handler and under our routes let us save this file again and under our route 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 route 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 of Jes we named our function as index and the only call it has is to a call called res dot render the resident render called 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 tag and the second argument is a JavaScript object with a key value pair the key is title and the value is expressed now under app dot j s we did define our view engine as pug and we did define that the views are located under the views directory so expressjs 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's an index dot Park 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 the parameter to pug so if you look at index dog park 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 by assuming that you've installed gates and I'm going to initialize a git repository here by typing git init DB and we've initialized a repository and you can check that we have created a dot skit 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 get ignore file having no bodies 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 ok coming back to the terminal I'm going to make my first comments by typing git add dot dot 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 - a meaning commits everything that is in the index to get so as you can see we have a bunch of files being committed and we're also including the git ignore file so let's like initial comments and save and exit and we have essentially committed our first change to our git repository to get the full source code for those 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 tutorial and if you have questions you can click on this button on the same page become a member it's free and then you will 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's a tool called node amount that we are going to install so I'm going to stop our web server and I'm going to install node 1 by typing NPM install node amount and then also typing save - dev what this does is the save dev will save node 1 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 node 1 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 standards node command but in case of development we're going to run node mom instead that monitors for changes in source files and restarts our web server so for the start scripts I'm gonna go ahead and type if the environments is production then we use node bin www else we use nodes one being www and then fi now this should work and we are going to use node 1 to monitor our web server so let's go ahead and try running this ok as you can see no daman 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 get comments because we've installed not much so I'm going to do git add package JSON and then git commit dash em install no more 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 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 gets landing so if we go we save this file and go to controllers index.js let's let's rename this file as landing jeaious 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 enable so I go under views landing that bug and right below this paragraph are 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 elements of type email and we're going to use a placeholder let's write your enter your email address notice how there is an indentation here Park nests HTML elements by using indentation so inside form we have nested and 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 submit' when this is a submit button that indicates that we're 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 so let's make sure all of the files are saved and if I now restart my application I should see the form being served by the center 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 its ads because we renamed some files we need to explicitly add what's to get add views it has rollers let's see if we have captured all the files I do get comments - a to commit all the changes landing that POG has been registered as a new file and so his controller landing of j/s but we missed views landing that Park so I'm going to explicitly add that file landing that part okay now if I commit we should be covered with all the files that we have renamed and added in gates I'm going to write a commit message landing page getting started and first form typically what in get 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 routes so I go to browse index j s and include a new router with the posts HTTP method and then I'm going to use a new handler called landing that submits lead because we're looking for sales leads it is called summit lead I'm going to save this file go to the controllers landing dot j s 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 dot Park there is this input elements we forgot to name it so where I'm going define a name for it called leads email when the form is submitted from that browser we're going to be able to access the value inside this input elements 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 that body lead email to print out the value I believe I need to include the package called body parser in app dot J's for this to work but it turns out expressjs already includes this functionality this allows us to retrieve the values for input elements when there is a handler for a post request you feed simply do-rag that body that 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 read that redirect and we're going to use the original path of slash so that we go back to the landing page for now so I want 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 controller's landing j/s it add routes index.js and we also modified our view file so we're going to do git add to use landing dot pug and comments landing page post routes 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 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 starts PostgreSQL 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 a database running we're going to use a tool called P SQL to connect to our database and make some changes so I am going to try P SQL Postgres to connect and if everything goes well you should see the poster SQL 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 TP user I'm assuming here that I'm going to use the name Express MVP for our application so I'm just adding a - DP user for that and with login passwords 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 command you can do that by typing a drop database or drop roll 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 C cool eyes as our choice of ORM if you go ahead and type sequel eyes in your browser we're going to find a website for it as sequel eyes is a stable and popular Orem for nodejs and it will work well for most of our needs and Oren 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 Orem lets you generate those queries by writing javascript okay so let's go ahead and open up our terminal again and type NPM install sequel eyes this will install Saku lies as a package I recommend doing - - a safe so that it's say - our package that 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 sequel eyes 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 sequel eyes called sequel eyes CLI so I'm going to install that as well by typing NPM install sequel eyes - CLI and I'm going to use - JEE so that concludes our installation for Postgres and a sequel eyes now we're going to create some configuration files so that our application and cyclists can access our database and for that we're going to use the tool a sequel eyes CLI but before we start we need to first create a configuration file for sequel eyes CLI so that's the default paths we use are going to be defined let's go ahead and create a file called dots equalized RC in the root of our projects typing a touch that sequel eyes RC and let's open up our editor when we open a sequel SRC 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 buy sequel eyes in it and we have created several folders the config slash config dot J's is the one we're interested in this is defines the database details let's open up our editor again and go to config slash config dot J's 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 define the database username as Express MVP - DP user as our password we defined one two three four five six and for our database these are the users and database we created using the P SQL command previously so we're going to type Express MVP DB and our host is hundred and twenty seven zero zero one 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 5 4 3 2 I'm currently not going to attach the other environments I'm going to save this one here so we should be now ready to access our database from sequel wise using our application now I'm going to go back to the terminal to commit some of the changes that we made so far and we installed secret lies and the PG libraries so we've modified our package that JSON file let's go ahead create a comment for that change we have added sequel eyes and teaching packages to save this comment we also defined a sequel eyes that our CFO so I'm going to add that one as well and commits this change configuration file for sequel eyes CLI and I've also created a configuration file for our database connection so I'm going to commit this file with git add convict of Jas there is also one more file that I'd like to introduce to you briefly under models when we ran seek realizing it we define the file called index of Jas this will initialize sicko wise when we run our application it takes the environment that we defined under config yes and then creates a new sequel eyes instance using the database credentials that we have created so this is the initialization file that was auto-generated when we typed sequel eyes in it so I'm going to check this file in as well and the file name is always indexed of JSON this is a specific file just for initializing sequel eyes so I'm going to commit these changes when we added configuration file for sequel eyes and the script as a recap for where we 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 sequel Iser 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 old migrations and let's create a new file under the models directory named lead that Jas since were collecting sales leads our table and model will be named leads migrations allow us to create recipes to take our the base states 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 cyclists to create to generate the methods for accessing the table and to update the table to take database actions on the tables such as creating rows deleting rows updating rows and fields and in contrast migrations are used or 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 are going to create is highly specific to cyclist cyclist has all level methods for accessing and manipulating a PostgreSQL database but the migration itself is a file a recipe that's specific to equalise 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 on 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 zero one zero four and then the hour is 1917 and I'm going to include the action that this migration is going to take which is creating a table names lead so create leads table and then finally that's AJ s 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 methods 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 very represented by a universally unique ID type and sickle eyes it has that type built in for us and typically we need a created at and update to 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 a sequel eyes string so we have saved this migration we can go ahead and run it by typing sequel eyes DB migrate the command has succeeded which means we have created a table called leads in our database now we need to define the sequel eyes model definition for the table we just created so let's open our editor and create a new file under models called lead jeaious I'm going to copy and paste the definition that I created earlier for this this JavaScript model file is specific to sickle eyes a secret eyes 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 Creator that and updated that fields in the model because sequel eyes assumes they always exist when we run the application sequel Liars will models index J s 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 model directory for each database table we define a model such as the one we created for Lita Jas for the leads table and sequel eyes we'll 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 being / www and here initialize sequel eyes for that we need to first create a variable called models and import the models directory and these three lines starts our servers listening on a particular reports we're going to modify this code a little bit and we're going to type return models that sequel eyes sink and then result I'm 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 sequel eyes 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 commit this file create migration for leads table or creating leads table and I'm going to check in the model as well it's add models lead jeaious we're also going to check in the changes we made on the initialization file bin / www initialize secure wise now that we have a database setup we can implement the post routes where we will save an email address to our database so let's go and open up our editor and go to controllers / landing jas 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 cost models equals require dot dot slash models models gives us access to the sequel eyes methods for the models that we have defined and I'm going to try to return models that lead that create note that create is a sequel eyes method and for the email field we're going to use the value we've obtained from rick 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 is your name at male comm and submit notice that the browser reloaded the landing page and that's because of the resurrect 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 sequel eyes ran by sequel eyes we're inserting a new role into the lead stable particularly the the 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 get adds controllers landing jeaious and then commit to change save leads collected 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 creates 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'll cover is for listing the leads so let's define a new route with the path slash leads and the handler called as show leads let's save this file and let's go to controllers landing dot j s to define our new handler let's copy and paste the first one we created it's name is 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 that find all and then we will be returned an object let's name it as leads and let's cut this line with the rest and ER 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 as synchronously 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 a synchronous and we'll get to those later and the final method is defined by Seco lies 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 video file usually typically we use a different view file for each purpose but for the time being we're gonna use the same landing view file to also show the collection of leads now let's go to views landing that Punk we're going to type if Leeds Park we'll check that if the Leeds variable is nonzero it's going to include the rest of the HTML snippets let's type if Leeds and then let's define a header here called text Leeds Park also has the capability of iteration we're going to do for lead in Leeds note that Leeds is an array of objects of type elite we're going to create a paragraph and type lead that email now part considers that anything of that comes after the pea is text we don't want to display this as text and we want to use the bug way of tag syntax of dereferencing this variable which we used here by typing hash open curly brackets and then close curly brackets let's save this landing file and go to our terminal our application is still 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 jas 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's the this new route that we defined is going to be triggered which will call this show leads function okay so if we go back to our browser let me submit a new email address lead one email calm 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 get as controllers landing J's add routes index Janus and and P use landing the puck implements these routes of needs submission now we want to take a look at the details of each individual leads so let's define a new route called slash lead / : 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 route adler show lead now let's go to controllers landing j s 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 but lead that finds one 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 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 review 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 the email now let's go to landing dot Park we want to give the user an opportunity to click on a link that takes us to the individual detail 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 leads 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 this character that I'm typing is used for text and also to display spaces in puck 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 Lita 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's 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 if ad views it adds controllers and routes and then comment now add a new route to display these details let's go back to routes slash index dot J's and we're now going to define the routes for editing individual leads so let's type router that gets slash lead slash : 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 that show edit lead now this is a gate routes 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 that post slash lead / : leads ID slash edits and define a new handler called edit underscore lead here the first route we define 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 gates and the post routes and this is because when 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 requests 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 editor out for the lead for that let's open up views lead that bug 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 that ID remember that we have the lead database object available to us so we can reference it's ID and also we're going to add the slash edit path for editing the lead now let's write it is 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 edits lead route by going to controllers and landing j/s and let's copy and paste one of the handlers here and call it show edits 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 manipulates each lead so I'm going to finally call this lead / edit the bleeds now let's save this controller and create a sub folder under views called lead and also create a new bug file called edits underscore lead that bug now let's go to landing that spark 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 opportunity to modify the lead so we can copy some code from landing that Parkway or where we already had a form I'm going to copy this form and input element and the button elements to edit plate now the action for our form needs to reflect the route that we define 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 Lita 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 elements 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 that Park at the beginning we need to update also our reference to go one directory level below now if we go back to our index J's file we haven't defined the route handler edit underscore lead for the post route so let's go to our controllers landing the Jas and define a new route called edit lead and let's delete the body now we have access to the leads ID by using records param studs lead underscore ID because this was available to us the route path we also have access to Greg body lead underscore email the actual updated fields and that comes from the edits lead form the name of the inputs 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 fields by using lead email let's go ahead and type return models that lead that update email brick body does 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 cyclist we're going to redirect the user to view the lead so we're going to use slash lead slash plus reg 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 okay and I'm going to open up the browser and browse to localhost 3000 let's create a new lead hello and get buzz that I owe 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 edits route and I'm going to shorten this to let's say a ATS be calm and save it and I'm redirected to the TRO leads 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 checking the changes we made so I'm going to type git add views and controllers git add route these are the directories that be modified and then we're going to comments as leads edit and post browse the next route we're going to implement is the delete routes let's go back to our editor routes slash index dot JSP the posts slash lead /li ID slash we're going to use the delete path coupons and then let's define a new handler called leads underscore lead let's save this file and then go to controller slash landing dock GIS 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 wreck param studs lead underscore ID then redirect back to the landing page because we are going to delete the current lead and everything associated with it building the page that shows the lead so that's my press that redirect slash leads now let's save this file but let's go to views lead lead that bug let's define a new action here we're going to use a button instead of a link because the default method for accessing the 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 meetup ID / 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 it let's go through slash leads let's go to the details or 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 we're ID is this ID this concludes our implementation of the delete routes as usual let's check in the changes we made we're going to do and controllers it's and routes we add views comments implements delete route or 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 does post / lead / 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 dot J's 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 lead throughout we're going to send back a JSON object and we will do that by typing res dots and defining a key msg with a value success now let's save this file and go to view / landing dot Park 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 onclick property of the button to call the JavaScript function delete lead on click is an event that gets fired in the browser when this button is pressed and by assigning it at 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 Park we surrounded with this character called the grave accident which looks like this tilted single quotes we're also interested in passing this lead the ID field to the delete lead function but also we want Punk to evaluate the value of it and pass the value and in order to do that we type dollar and then curly braces leave that ID and we surround the results 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 Park 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 javascript slash leads j/s so let's save this file and go to Java scripts slash leads Egeus 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 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 pass 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 JSON and then we typically pass the data payload in this data field and JSON dot 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 dot 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 delete' from our database using the HX 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 HX call happened in the background for that reason we need to modify the currently served HTML page for displaying in the browser we do this dynamically in JavaScript and delete the HTML that corresponds to the lead that we have deleted the currently served HTML documents 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 are 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 elements we want to delete so for that let's go to views slash landing that bug to this paragraph elements for each paragraph we create for an individual leads 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 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 dot Ajax means you'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 wanna 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 particularly tidy jQuery we'll 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 leader out 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 it's chicken the changes we made I'm going to do git add controllers and routes get add views we've also defined a new javascript file so I'm going to do git add public JavaScript let's call it this implement lead delete routes using Ajax in this tutorial we're going to update two 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 get bootstrap calm the easiest way to include bootstrapping our project is to include hosted CDN links of the library in our project files CDN shorty 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 park files into reusable components and we're going to create a header a nav bar 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 heads dot Park footer dug and nav bar dot pocket let's go to head that pocket like mixing head title indent head meta charset equals beauty title equals title part mix-ins allow us to define common snippets and include them in multiple Park 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 style sheet think cut it and paste it on head that bug and change the syntax to Park 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 tab and type mixing 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 tags syntax to use the Pug syntax which is script and then open parentheses some properties and close parentheses now let's do this one as well now the order that these libraries are declared mater 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 bug so let's go there and delete these first few lines and type doctype HTML HTML blankie cools en and we're now going to include common head that Park 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 that J S which depends on jQuery I'm going to add the footer include common foot through that Park and intermixing and we don't need this find anymore because we've declared jQuery in photo dot bug 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 it let's conclude our tutorial by doing some maintenance work the other POC file that we used was lead that bug 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 sale we also are not going to make use of this layout of park file anymore so we can delete that let's check in all the changes we made I don't have to type get and use common key to add views and get comments add a common header and footer section in all part 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 the bug now under the body I'm going to copy and paste a bootstrap now bar 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 park the first elements you define is the HTML element and then everything that comes after that separated by a dot our CSS classes CSS classes modify the appearance of your HTML elements so in this navigation bar 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 park but this line does not contain 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 and it will be assumed that the first element is a div element we're also making use of an image asset file or 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 outlet 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 navbar from here and place it in a common mixin file so let's go under views / comment / navbar that POG we created earlier and paste this code we're going to define a new mission called navbar and currently we're not needing any arguments and I need to indent this by one level under mixin and save the file now let's go back to landing dot pug and include our mixin on their body we first need to add a header tag include common slash navbar dot Park and then + 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 role and then inside the role 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 let's 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 dock bug 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 other title leads and then we start a table inside the table under this tea 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 tea 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 what it's deleting the lead so as a recap if you go under public JavaScript's leads is at Jas 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're nesting this table and that's not correct so I'm just going to be 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 routes and also let's go to footer duck pug remember when adding a dependency for the bootstrap library we added this jQuery 33.1 and then the slim version turns out the slow 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 not 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 part let's save this and we should now be ready to run our application let's go to our browser and reload the homepage and let's click on the leads link and if you 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 checking all the changes we made so I'm going to do get ads Boosh common get add use landing bug and let's try doing bit comments and let's type installed 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 it lead and create a new file and save it as leads that's 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 call Youm it's a copy and paste those these are nested on their body and Heather and let's cut and paste the section for leads were actually not going to use these two lines in the landing page either so let's delete those save it and under leads we're 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 dot Jas once we submit a lead were redirected to the lead route and once we show the leads instead of using the landing page we're going to use the new page we've defined and that will 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 that 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 two leads and I'm also going to move this lead the Pug file under the lead directory so let's just do that you leave the Pug use lead lead the pug and I'm also going to update the CSS classes here to match the ones we use on their leads and to use bootstrap so let's copy and paste the code we have four leads the plug-in to lead that bug 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 four 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 edits 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 leave that 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 slash lead slash me the ID deletes so let's delete this portion and the body let's save this file and let's go to controllers landing page is when we render the lead page that is now located under the lead slash Lee 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 Park 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 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 on our changes in this tutorial we're going to develop sign up and login functionality and learn how to works let's open up our editor and open route slash in XJS 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 that get for sign up 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 GS 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 signup 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's for 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 the bug and sign up that park 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's 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 for the option of going to the logging routes now let's go to login that pug also I'm going to paste the code that I prepared for this it's essentially the same code except we're posting to the loading routes 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 option little 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 us 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 J s since we covered one model definition in detail for Lee J as 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 B defining an ID and then we have several fields of type a string we have a user name 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 now true so that we can create rules 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 since we've covered a migration example before so as we covered previously the migrations have two methods one is an up method 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 were 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 sequel eyes 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 D pad controllers get add routes commit implement get route for logging 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 get comments create user model and migration now let's open up our editor and go to route slash index dot J's we're going to define the post routes for login and sign up so let's type router that post slash login user login router that post slash sign up user that sign up now before we move on let's define these controller and routes as well so let's go to controllers users that Jas and create these two empty handlers sign up and log in now we're going to implement the sign up and login routes using a node.js library called passport J's in particular passport J's 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 and if you're interested to find out more you can go to passport j/s that 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 sign up browse 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 - flash so let's type - - 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 - adds package it up JSON get that package lock that JSON and comments Express session and connect flash now let's go back to our editor we're going to go to fjs to create an instance of passport let's type let passport equals require a sport we're also going to define the session so let's session object equals require Express session and let's go down below right after this line we're going to declare app that 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 apt of use passport dots initialize and finally app that use passport dot session each of these calls must be in this given order otherwise your application may not work because when fjs 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 a pop J's in order not to clutter up the J's with details of passport J s 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 j s and save now in passport setup juice 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 statements and we're passing the passport instance we create a few lines earlier so let's go back to passport dot set up now passport J's requires us to define a few well defined API calls to function properly the first function is called serialized user and the second one is called deserialize user this Stack Overflow page explains it quite well serialize user is used by passport J's to save a handle to the user object in this case it's the database ID for the user it's then saved to a session variable and later on the serialize 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 Jace and define these functions you realize user we're going to simply use the database ID and for this serialized user we're going to query our database or 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 an error object from user ID and else we're going to call done now 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 de-serialize user will retrieve the user object using that handle now we need to define a strategy for passport GS 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 has 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 jas that we will be using the local strategy for authentication for that we added statements passport dot views new local strategy local strategy will call its authentication function when there is a login form submitted via a post request so what cool strategy needs to know which fields in the submission contains the username and password for that there are two optional fields to define these username fields in our case it's called email and password fields and in our case it is called password now if you go to login that part you will see that the first input field is named as email which we will use as the user name and the second one is named as password so when the local strategy accesses requests body email it will consider that as the user name 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 as 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 pass reg to callback true we're going to use this for error handling later on now let's define our function let's open up 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 now it means we couldn't find the user so we're going to return on error message incorrect credentials and we need to add return done not false and we're going to type else if user that password is null or user has is defined brick flash message you must reset your password these wreck flesh messages will be shown in the subsequent rerender of the page and we're also going to type return done now 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 in correct credentials and this will be entered if the password isn't valid so I'm going to add a knot and here we're going to type return done now false so we've handled all the error cases and if we have a valid user we're going to return done non user there may be further errors other than incorrect credentials being provided and we will handle down 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 statements 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 passport validation we need bcrypt library so let's type require bcrypt actually for accessing the models the database we also need to define the models variable my 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 bcrypt function we will pass the password in the login form versus the user that password fields 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 adversary's 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 objects which is to be saved in this session and then passport Jes will use this handle to get the actual user object from the database we also define a local strategy where we tell passport J's what feels to use for the email and password fields when authenticating the user post requests during authentication there may be various errors once the database is queried even 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 neat and after Jas it add a sport set of J's and gains moments a implements a sport local old strategy using email and password fields now that we have set up passport J s we can go ahead and use it in our sign up and loading routes so let's go and open up controller slash user J s in the side appender 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 user the bills email break body email and password we're going to use a function to generate the hash of the password so let's call this function generates hash and we're going to pass break 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 result and inside the body of this promise we're going to make a call to passport j s to authenticate the user after sign up 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 it will call slash signup and we're going to define a flash message failure flash true we're also going to pass the requests response and next objects now in order to use the models object we need to first define let's models equals require dots 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 think so return bcrypt hash sink password V credits can salt sink eight 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 bcrypt object let's be crypt equals require be crypt let's also defined passport it goes require passport you also need to set up passport so let's start const my passport equals require dot dot passport setup and we're passing the passport instance we also will need flesh so let's dive 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 client now let's save this file and run our application and verify that the sign up works i'm going to run the application go back to the browser and type slash signup let's type user an email calm 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 routes in login route we authenticate a user 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 loading route let's check the result by going back to our browser and let's fight slash login let's type user at email calm and then the password and I'm going to click on login and then redirect it 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 dot J's and for completeness we're also going to define a logout route so let's type router that post slash lockouts user dot logout and router that get slash logout user logout for both requests we're going to use the same method now let's go back to controller's user J s and define a new method called Lobell we can destroy our session by making a call to rec log out and rake session dot destroyed and we will then redirect the user with Red's that 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 view slash navbar dot Park to implement this I'm going to paste the snippet that I prepared earlier here if we are past the 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 logout login and sign up 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 dot pug and pass the user variable to the navbar mixin let's save this file and now let's go to controllers slash landing j/s we're going to pass the user variable to the render function so let's type user rec dot user if you recall passport Jes will populate this rec dot user field with the user object if there's 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 use your pet's 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 logout 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 in plan it's signup moving and global droughts using passport j/s 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 slash index.js here we have defined a post request handler for signup path using this user that signup handler so let's open up that handler by going to controller slash user dot j s if we look at the sign up post handler we see that we create a new user object without validating the input we received from the form req body email and read body 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 the validator we are also going to use a package called lodash so let's add that as well and by - - save and press enter let's commit our package that JSON just in case we made any changes I'm going to type get comments packaged of JSON and package lock but JSON okay they install later and - 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 sign up top j/s here let's 5 lets validator equals require validator say that and i'm going to create a local function cons well date create user fields function this is going to receive an error 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 req parameter which is the request object so let's like if validator is email break 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 statements 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 recta body that 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 break body password here we pass a length range object with minimum of 8 characters and max of 25 then again we're going to populate the errors or the password key please ensure that your password has a minimum of 8 characters now we're done with this function because the airless 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 with 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 exports validate user function tears rank type return models user find one where email is req body email and then we are going to get value u if u is not equal to mouth then we're going to populate the email key of the errors object email is already in used please log in 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 a synchronous and we need to mix the two together for that we need to use a concept called promise and make the entire body a synchronous 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 a synchronous 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's inside the promise and let's make a call to validate create user fields there's rec and they 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 fools require toppdogg / models now let's save this file now let's go back to a controller / user J s and import validate user so let's type Const validates user equals require toppdogg validators / sign up now let's go down to the sign up 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 req 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 rerender the form just as we will render the form for the first time using the show sign up enter 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 read rest 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 is one more thing we forgot this is an empty function is a call that's been provided by the lodash library we just installed so we need to type Const is empty those require low - now is a good time to define our rerender sign-up 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 buy a Const pre-render sign up now even though rerender sign up looks like a request handlers 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 expressjs the request handlers have a particular order in their parameters in particular the request response and next objects are passed in that order so rerender 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 rear-ended 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 rerender 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 saved the user time by passing back the data that's been entered already in a previous submission so in order to pass the data back to form data key we are going to use rec that's body if you recall if we go down to the signup handler when the form is submitted to us we have all the form input fields available to us in regular body objects with the keys corresponding to the input names such as email and password so by passing back correcta body after mission we are effectively passing back all the input fields that have been submitted to us on the form submission so we're passing reg that body back in form of the key form data now if you recall show signup is using user slash signup view and we're using the same view in rerender signup as well so we're going to modify the signup view to cater for both cases of the showing the form for the first time and also rerender in the form with errors and existing form information so let's go ahead and open up views slash user slash signup that bug 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 that 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 there's that 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 of 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 there's the 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 go to the slash signup browse 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 full character password which should also trigger on there so if I click on sign up I took it 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 that's checking all the changes we made it adds validators we've added the new directory validators and we've implemented error and link and form validation or signup 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 expressjs 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 dot JSP is 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 novel and place a comma and let's define not with constant no equals function req res next and an empty body as you recall the handlers in expressjs have this particular function signature where there is first a red 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 match the first function to be called is going to be knob and knob 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 knob 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 of course 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 requests for this route that's why they're called middleware middleware may sound like a grant term that does something complex but a middleware can merely be a simple function call such as this log function and let's remember that in a middleware function we always need to make a call to next in order to precede 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 this knob 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 off KS let's like let's 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 dot J's and it comes as standard with the button like Express J's installation so let's go back so let's define a new method exports is lured in equals function rec res next if rec dot user then we will call next the presence of rec that user means that passport Jas has authenticated the user there is 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 is 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 or we call next which should normally call the next handler for this route while the answer is in the Express documentation if you pass anything to next function expressed 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 dot J's 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 most cases of a success and error let's save this file and go to index dot J is in the rouse 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 off J 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 that bug 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 ready 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 login I'm going to type user at email cone 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 but save this file and go back to our terminal and type sequel eyes DB migrate so we've successfully migrated our table and added an is 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 / UJS 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 signup handler let's type return model's 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 role as normal so let's cut and paste the way we creates the first user and else we're going to create the user what 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 es admin field so let's create an easy admin field under here at the bottom I'm going to copy and paste code prepared for this earlier so is admin is a boolean and we allow it to be now because the existing users won't have a 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 password for that and press sign up now we have admin at email comm signed in and let's go back to our terminal to verify that this user was indeed created with his admin as true insert into users first second third and fourth field is is admin and I can confirm that admin at email comm 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 slash has all J's and I'm going to define a new function here exports but has off equals function read press next and if rec user is not mall and and rec user dot is admin it's 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 route slash index dot JSP this new method has off and we're going to replace the is logged in middleware with this one so let's light has 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 thing 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 calm and login and if I now click on the leads link I am 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 off for shortly as off for the Edit lead and the rest now all of our routes are protected by the has Al's 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 if migrations its comments - pay and implement has of middleware and is admin like lead routes are protected as and only the admin user has access to them I hope you enjoyed these tutorials my name is brother I'm a system software engineer my background is in low-level software and operating systems if you enjoyed these tutorials I 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 the low 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
Info
Channel: freeCodeCamp.org
Views: 235,972
Rating: 4.8883109 out of 5
Keywords: node, node.js, node js, express, expressjs, express.js, express js, api, restful, backend, javascript, express tutorial, express.js tutorial, restful api, nodejs express, restful api tutorial, express rest api, node api tutorial, server side, mean stack tutorial, mean stack, server-side javascript, learn mean stack, node api, express api, mean stack tutorial for beginners, mean stack app, mean stack application tutorial, postgresql, bootstrap
Id: G8uL0lFFoN0
Channel Id: undefined
Length: 148min 13sec (8893 seconds)
Published: Tue Feb 12 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.