Node.js / Express Course - Build 4 Projects

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
improve your node.js skills by building four projects this course is taught by john smilga the wonderful instructor from coding addict what's up everybody this is john from coding addict and welcome to another nodejs video and in this video we're going to make four node js projects while working on the projects amongst other things we'll cover what is mongodb and how to set it up in our app how to get up and running with mongoose how to set up error handling in express and eventually we'll deploy our project to heroku and implement swagger documentation as well just like my other videos we'll start with the fundamentals and slowly but surely move up to more complex functionality this is the second part of node.js tutorial video so my assumption is that you're already familiar with nodejs and express basics if you're interested in the first video node and express tutorial you can find the link in the description in order to follow with a project you will need a starter and the fastest way you can get it is by navigating to johnsmilk.com again the url is johnsmilk.com and once you hit this lovely site look for the projects more specifically node ones and then all of these three links lead to the same repo so you can pick any of them and once you click you'll navigate to the repo node express course and essentially in here just pick your weapon whether you want to download zip or if you just want to clone it i think in my case i'm just going to go with download option then go back to your computer look for your downloads then crack open the zip file and right away open up your favorite editor in my case that is visual studio code i'll drag and drop and during this video will work on following projects so we'll work on zero three task manager store api as well as jw2 basics and jobs api and for all the projects you'll have the same structure where there's going to be a final and a starter so final is a complete project and starter is where we'll do all of our work now keep something in mind where for the final one not only you'll need to install all the dependencies basically run npm install but you'll also need to add some additional info what info well that we will cover during the project so don't be surprised if you just run npm install and npm start in the final folder and you get back bunch of errors that's about it for overall setup and when it comes to project specific setup i'll cover that right after each project intro video so once you've got the repo in your text editor feel free to continue with the video awesome and welcome to our first project task manager api and before we cover the features let me list the main goals of this project and they're following with the help of this project we will learn how to set up and connect to the cloud database so effectively we'll learn how to persist our data to the cloud and not only that we'll also learn how to perform all the crowd operations and crud stands for create read update and delete on our data which is fundamental fundamental to any application also let me mention that since it's a node course we'll only work on a back end so essentially the front end app you see right now is already prepared for you and it's only there so you get the full picture and the same is going to be for the rest of the project i'm probably not going to make front ends for all of them but if i'll see that a matching front-end app can provide more clarity i'll definitely whip up one as well just so you can see the entire request and response cycle not just post my responses as far as the first project on the front end we've got a form analyst and by communicating with our backend meaning by sending requests to our api the user can create read update and delete or destroy tasks again let me stress something this is not your typical to-do list app that stores everything in local storage what's fundamentally different is that we're going to be responsible for setting up the api that communicates with the cloud database and persist the data to the cloud and as far as the functionality it goes something like this where we have the form and of course i can enter a new task that's exactly how i'll call it we press submit so we send off the post request and since we're successful we get back all the tasks and the newest task is added to the list now we can also delete task so if i don't want to walk the cat i just removed from the list and then if we want to edit we click over here and first we'll see only the specific data about that one task and then if we want to edit for example if i want to set it up as completed and if i want to rename it as old task then of course we just press edit then we send off the request and now if we navigate back to all the tasks now as you can see it is completed and the name is different as well and as far as the task manager setup like i already previously mentioned we have final folder so this is where you'll find complete project however not only we need to install all dependencies but also if you take a look at the readme you'll notice a text where it says in order to run the project you need to set up dot env and set up the uri connection variable and essentially these are the things that we'll cover during the project so in order to spin up the project yes you'll have to watch some videos where we actually cover that and only then you'll be able to do that now as far as the setup a lot of things should look very familiar so in here we have the public and of course in the public this is where we have our app again everything is already prepared for you and just so we all are on the same page i actually created that with vanilla.js and then of course we have the app.js and here i simply have one line task manager app and then if you take a look at the package.json as far as the packages we have express something we covered in the second part of the course and then you see two more packages dot env and mongoose and of course these ones will cover during the project why they're there and what is going to be the use case now in order to make our dev setup easier i also installed nodemon as a dev dependency and as far as the script well you just need to type npm start and that essentially will spin up nodemon with app.js and then we also have git ignore which we're going to cover a little later once we create the env but long story short this is just a file that prevents specific files being added to the source code and essentially with this setup these two things will be ignored if we decide to push this up to the github so we'll ignore node modules because usually they're pretty big and then dot env because this is where we want to keep our secrets and of course we will cover this one later in the project and once we're familiar with the setup let's kick things into gear and actually start working on project and first thing that you need to do is to navigate to the starter folder again you're looking for the third project the task manager and then more specifically the star folder and i think the fastest way to navigate there is by just typing cd and then grab the star folder and drop it here and then once you're in a starter before you do anything make sure that you install all the packages and of course we do that by running npm install and then once all the packages are in place in order to spin up the nodemon we need to go with npm start unless of course you want to change it to a different command if that's the case then make the changes and then use that command instead so in my case i'll just wait a little bit i mean it shouldn't take too long there's not that many packages in there and then once i have all the packages in place then of course like i said we're gonna go with npm start and if you see task manager in the console we are in good shape and now let's set up the most basic express server which essentially is just going to be listening for one route forward slash hello and it's going to be on port 3000 now if you want to jog your memory and test it up yourself just pause the video and resume once you're done if you don't want to do that just keep on watching the video and the way we set up the most basic express server is by setting up a variable by the name of express then we'll set it equal to require and that's going to be equal to our express package then we need to initialize it so we go with app and that is equal to express and we invoke it and then unlike the previous examples we'll actually set up a variable by the name of port and for time being we'll hard code this to 3000 but eventually there is going to be more code and i'll talk about the reasoning later so for now just set up the variable and we'll be in good shape and in here we need to go with amp.listen of course and first thing we pass in is the port and the second is the console.log so we go here with some kind of text and i'm going to go with server is listening on port and then of course we pass in the port value and i always like to add those three dots as well so i'll do it in this case and then i'll open up my console the moment i have server is listening on port 3000 which is just awesome so now let's also set up that one lonely route so above the port i'm going to go with my comment routes and then we'll just say app.get so this is going to be a get request now what is going to be the url well we'll go with forward slash and hello so that's going to be the path and then of course we have the callback function once the user hits the route and we're looking for iraq and res so request and response and we simply want to go with reg dot send and then we'll pass task manager and app so i'll save it here i'll navigate to the browser and i'm looking for port 3000 of course and then we'll go with hello and if we see task manager app displayed in the browser then of course we are off to the great start beautiful and once we have the bones in place next let's take a look at our application so we can decide what route eventually we're going to have and i can see that i'm getting all my tasks so there will definitely be a get request that gets me all my items now i can also create a new task so there will be a post request that can create a new task now we can also delete one so there will be a route for that and if we click on edit we open up a new page and in here we get info about specific route so there will be a get request that just gets me info about one single task and also we'll have the ability to edit so if i change the completed from true to false if i successfully edit that then if i go back to the tasks of course in here i don't see the check mark which means that i successfully edited the task and what that means is that there's also a route for the update and in summary our routes are going to look something like this where there will be a get request on api version one and then tasks so this will get all the tasks then there will be a post request on api version 1 tasks again the same url however the method is different so total different functionality in this case we'll create a new task and then we have guest route with params so with the id of the task that gets us that single task and of course one for update and one for delete and since there's a lot to unpack over here i'll spend the next video on the reasons behind such api structure all right so let's go step by step and probably your first question is well why do we go here with forward slash api and then version one and essentially that is just a convention we need to understand that on the server we also might have different routes not just the routes for the api so for example you could be serving a index page here on a forward slash meaning there could be a nice index.html page that you're serving up over here and then also on the same server you have the api routes so convention is effectively just to signal that all of these are the api routes now as far as the version well as you're setting up the api eventually you might want to change some things so it's easier if you have this version because that way when you create a new one then you can just direct everybody to api and then version two three or whatever and while we're still on that same note why don't we navigate to a hacker news one the one that i showed you previously with algolia and you'll notice exactly the same setup more essentially they go with domain and then forward slash and then api and then version number one and that leads me to my next point where if you're ever in doubt or if you're just interested on different setups just check out the different apis there's tons of apis out there and you can just look for one then take a look at their setup and then decide if what they're doing makes sense to you then of course you can implement in your project if not then just move on to a different api and eventually you'll find a setup that makes the most sense to you after that you're probably wondering okay i understand the api high-end version that kind of makes sense but why do we go here with get and then tasks then we have the post and the same tasks and then for get patch and delete we go to the tasks but then we're looking for the colon why isn't this written in a different way where we're just looking for a single task or something along those lines and to give you a short answer that is a convention but since there's more to it i want to actually cover that in a few videos so i want to set up the basic routes with just some simple responses then i want to open up the postman and do a little bit of setup over there and then right before we start setting up the database i actually want to spend one video on just talking about the convention and then lastly if you remember in tutorial we worked with put and now for the update we're using patch and i know that this might be a little bit frustrating to you but that's also going to be something that we will cover a bit later once we have already a working application because that way i believe that i can give you a solid example of the differences between the put and patch that's about it for the general route structure so now let's start implementing it not bad that bad i think we're good with the general structure so now let's start implementing it and i want to right away set up the router as well as the controllers and if you remember at the very end of the express tutorial i covered why is that necessary and essentially the short answer is that as our application grows bigger it's not going to be very sustainable if we'll just start dumping everything in the app drives and for time being i just want to create this one route now as far as the response it's just going to be a simple string that says hey here are all the items or something along those lines and then once we have that one in place then we'll add the rest of them and then we'll test it out in postman so let's get cracking and i'm going to go with new folder so here will be all the controllers and in this case i'm going to be looking for tasks and i also want to set up a routes folder so in the routes folder we'll go with new file and same thing we're going to go with tasks js and then as far as the setup in the routes we need to look for the express router so say const express and that is equal to require and then again we'll look for express and this should be a refresher because we did cover that at the end of the express tutorial so just to jog your memory if we go back to express tutorial and then more specifically we'll look for the final one the file 13 the router people shows a basic router example and essentially we have two options we can either go with route or get and then add all the controllers one by one or we can actually change them together where we go with router and then user route so this is going to be the main route in our case api version one and then tasks and then we chain get and post and i think i'm gonna go with this setup so first let's start by setting up the router and that is equal to express and then router we invoke it and then eventually we'll import controllers but for now of course we don't have any so let's just leave that one blank and we'll go with router router then route like i said then forward slash and then i want to go with get method and for time being i'll just hard code the response over here so say wreck and res and res dot and send and like i said we'll just start simply so say all items now let's save that one and then all the way in the bottom we want to go with module exports and that is equal to our router so now back in the app.js we want to import the router we want to import our tasks and we want to set up the middleware so in here let's just go with const and then routes and that is equal to require and then like i said we're going to be looking in the routes folder and then more specifically we're looking for tasks and then right after this hello and don't worry we'll change that one a little bit later for time being it can just stay the way it is we'll go with app.use and then of course what route are we looking for well we want to go with api then version one and then tasks so that's going to be that root route for the tasks router and then we just want to go with our routes and you know what let's just change the round but for some reason i went with routes let's just call it tasks i believe it's going to make a bit more sense and since we'll be sending json from our application for example when we're creating a new task and since i want to access that data in my routes what we need to do of course is get middleware that is built into express and that middleware is express json so above the routes we'll go here and i'll try to spell this correctly since that is always an issue hopefully this is correct middleware and then we'll just go with app.use and eventually we'll set up the static one as well but since at the moment we have barely any routes i'm just gonna go with express and json if you remember if we don't use this then we won't have that data in rec.body so i'll save it here and i'll leave the comments just so we all are on the same page and before i test it out in the browser let me just double check so i'm using the middleware where i'm saying that i'm looking for api version one and then tasks and then i pass in my router my tasks router and then in the router effectively i have this root path which just matches whatever i pass over here so again i go with api version one and then tasks and then i set up a get route where i manually pass in my controller and here i just say res.send and i pass in a string of all items and looks about right so let me go here and we're going to go with localhost 3000 since it's a get request of course we can access it then api version 1 and then tasks and we should see a string of all items and if we do then of course we're heading in the right direction so the last thing that i want to do in this video is to first close my express tutorial one and then in the controllers we want to create a new file and we'll call this tasks.js and again just to jog your memory the whole deal why we're setting up separate routes and separate controllers because if i'll try to jam everything in app.js it's going to get messy pretty fast so what i want to do right now is take this logic and place it in a separate file because eventually of course there will be way more logic than just res dot send so i'm going to go to my controllers and effectively i want to create my function the controller function and i'm just going to go with const get all and then tasks and i'll set it up as an r function i'm looking for rec and res and functionality will be exactly the same whereas dot send and we're just going to go with all and then items and then we're going to go with module exports and since i'm going to add more functions in here i'll right away export it as an object so say get all tasks that's when i'm exporting and then back in the routes of course i want to access it so i'll say here that i wanted the structure get all tasks from and of course we need to require it and in this case we're looking in the controllers so i'm going to go two levels up i'm looking for controllers and then more specifically task so instead of hard coding this value of course i'll just pass it in and i'll say get all tasks and if i go back to my url and if i can still see all items then of course we are in good shape and let me just test it out where i'll change this around and i'll say all items from from the file and then if we go back yep we still have the correct result and with this in place now we can set up the same basic structure for rest of the routes as well beautiful and in the same fashion let's set up the rest of the controllers so we have the get one now i want to create one for the post one for get but that's going to be a single item and we also have one for patch and one for delete and pretty much in all of them the setup is going to be exactly the same as far as functionality i'll just send back and i'll say what the controller is doing since of course we haven't connected to the database or anything like that and i just need to come up with a name in my case i'm going to go with create task and again we have rack and res and then we want to copy and paste since i want to speed this up and i'll just say create task create task and why don't we change this one around and we'll say get all tasks now we want to copy and paste and we'll have three more we'll have one for getting task so get task and here we'll say get single task then we'll have one for updating and that's exactly how we'll call it we'll say update task the same is going to be over here and then the last one of course will be delete and then task and you guessed it we also need to change the text and now of course we want to place that in the same object so let's go with create task then get task and we have update task and last one is delete task and then back in the routes of course we want to import them so say here create task get task then update task and delete one and now we just need to set up the routes if we take a look at the app.js these two the get and post are gonna go to api version one and then tasks and then the rest of them are going to be wii d id params so same initial path but then we'll just add the forward slash and then id and that's of course is where we're going to pass the id of the task so where i have the get request to get all the tasks i'll chain dot post and of course which controller are we gonna use of course the create task one and then we can simply go to the next line and we'll go with router then route and like i said we'll go with forward slash and then id and then we're looking for get route and that will be equal to get the single task then we'll set up our patch and that will be equal to update task and then lastly we have delete one and now we'll be equal to delete task now since we know that we can only really test the single task and get all tasks because that's the default method the browser performs we'll stop over here and in the next video we'll spin up the postman to quickly test all of our routes because trust me you don't want to go any further without knowing that at least the basic setup works because you can set up whatever logic you have over here if there's a small bug and you cannot access these strings then you'll spend way more time later searching for that bug nice job and once we have the basic structure for all of our routes now let's test them out in a postman so i'm gonna head back to my desktop i'm looking for the postman and since in this case we'll spend way more time over here i also want to cover some configuration options so for starters i want to switch to a dark mode because i think you'll appreciate that more so if you want to do that as well just go to the cog and then you're looking for the settings here and then in the settings just look for themes and of course we have a dark theme as well so that's the first thing that i'm going to do then we want to create a collection now why would you want to do that well since we'll be setting up multiple routes and they'll reference the same application which is going to be easier as we create more and more applications and in order to create that collection we go here and click on creating the collection and for starters i just want to change the name so i'll click on these three dots over here and of course we're looking for rename and then i'm just going to go with 0 3 and we'll call this task manager now if you're not happy with this name of course pick your own one and once i have the task manager then we want to start by creating a request so we create a new request it's going to be a get request and instead of typing all the time manually here local and then host and we're going to go with 3000 and then of course api version 1 and then tasks what we want to do is set up a global variable now there's multiple ways how we can do that you can actually set up the environment so think of this as a dev environment and then you can have production environment but in our case we'll just set up this localhost and then 3000 api and version 1 simply as a variable and you can do it from here as you can see they even give you a suggestion on all that but i'm just going to go the long route where we click here on that eye and then notice i have already won for the url i have localhost 3000 and then i actually changed it later to forward slash api so now what i want to do i want to showcase how we can remove it so if i go over here and if i remove it and i set up a new one in this case again i'll call this url and then as far as this value well i'm just going to take this whole thing so i'm going to go with localhost and then 3000 and of course we're looking for api and if you want you can also include the tasks but in my case i'll stop right after the version one so let's copy that one again i'm setting this up as a global but you can set it up in the environment as well and then once we add that we should be able to right away access it so now of course we just need to save it and then in order to use it we need to go back and you know what i'll remove everything for now and if we go with these double curlies this is going to give us access to those variables and all the way in the bottom we have the url and of course as you can see it is global so in here i'm going to go with url i'll close it and then i'll go with forward slash and then tasks and once i save i should get back get all tasks and of course that means that our basic setup works and before we continue and do the same thing with the rest of the tasks now of course we want to save it and not only want to save it we want to save it in our collection so let's click over here save as and let's give it a more meaningful name and in this case again i'll say get all tasks and of course we're looking for task manager so this is going to be saved in this collection and we simply click on save so if i take a look at my task manager now of course i have get all tasks where we use the global variable and we can successfully see our string and i'll close few of these tabs because it's getting quite busy and let's do the same thing for the rest of them so in this case i'm going to be testing the create one the one for the post that's why we need to change the method that's the first thing you want to do then we'll go with our url again we'll close it out forward slash and then tasks and remember now we want to send some data correct now we're not doing anything with that data on a server but just for the kicks why don't we send it i'm going to go here with body then we're looking for the raw and of course we're not looking for text we're looking for json we just need to make sure that we use the correct syntax and in this case i'll say name and that will be equal to testing and we just click on send and if we can see create task we are in good shape now since i also want to test out whether my middleware is working i'm going to go back to my controllers i'm looking for create task and in here instead of just going with send we're gonna go with json so now i'll be sending back the json and i'll pass in reg.body so if you want of course you can log it on a server but in my case i think it's going to be faster if i just send back whatever i'm getting from the client so if we go back and if we change this around and we'll say here shake and bake and if we add a comma and then completed we set to true once we send that should be our response and of course the only thing that's left to do as far as the create route is go to save as and then we'll say create task save it and now let's continue again i'll close these ones just so it's not that busy and in this case i want to go with get route then we want to go here with the url again and of course we haven't set up the database so there's no real id but we can definitely test it out if we just go with tasks and then whatever gibberish so in this case i'm going to go with hello so that's going to be my id so we're not sending anything as far as data but we are using the params again if we take a look at the routes we can clearly see that we have forward slash and then id that is going to be our param and if we want to test it out where we have get task of course we have the request and the id is sitting in the params so in here i'll do the same thing i'll say json and we'll just say id and that one is equal to rec params and the id so if we save here and then go back and just use the get route and click send we have the key with the name of id and then the value is hello so if we'll change it around and if we'll say peter of course the value will be peter again same spiel we got save as and we'll name this update task or i'm sorry get single task my apologies get single task we'll save it and then we have two more we have one for update and one for remove and in order to speed this up i don't think i'm going to do any testing anymore we simply want to open up a new route we want to go with patch in this case and again we're going with url and then forward slash tasks whatever value you want to pass in over here so i'm going to go with one two three send and of course i have update task beautiful let's save that one and we'll write here update and task and the last one of course is delete so let's close these two and again your request we're looking for delete method the url is going to be exactly the same and then we want to go with forward slash tasks and then any of the ids that we have already used since we'll change that later anyway and once we send the response should be delete task now if you don't want to go with save as you can simply click on command s that's going to be a shortcut and we go here with delete and then task and of course we save it in the same task manager and once we can clearly see that we can access all our routes correctly then we can move on to our next topic okay and once we're done with the postman before we start setting up our database let's quickly talk about our routes more specifically why we use such structure long story short it's because we're building a rest api and since these days the term api is used pretty much for everything let's just all agree that in our case since we're building a server essentially we want to create a http interface so the other apps most likely front-end ones can interact with our data that's how we view api in the scenario and when it comes to rest it stands for representational state transfer and arguably the most popular api design pattern and essentially it's a pattern that combines http verbs route paths and our resources aka data so effectively rest determines how the api looks like now let me emphasize something it's a pattern not a strictly enforced set of rules so nothing stops you from setting your own api in totally different manner in fact if you have used apis on your front-end apps you know that some of them have totally different structure i guess the best advice i can give you is this whatever pattern you decide on stick with it or in other words be consistent otherwise it's just going to be very confusing for your users and this is a common approach where you have the main list so that could be orders that could be customers that could be items whatever and of course in our case it is tasks and in order to get all the items we go with get method and then if we want to create one it's going to be the same endpoint but we just go with different method and of course in this case it is post and not to be redundant we already discussed this before but just because they have the same url the same endpoint since the methods are different in this case we have get and of course in second scenario we have post these are two totally different requests please keep that in mind and then for individual item you have the same path pretty much so you have api and then tasks orders customers or whatever and then you just use the params to point to that one specific item and then if you want to get the item then of course it is a get method for update you'll use put or patch and then to delete one you'll use the delete method instead and since json is a common format for receiving and sending data in rest api we'll use that approach as well so even though at the moment we use send method in our routes eventually we'll switch to json method instead also i'd like to point out that rest in general is somewhat fuzzy in fact oftentimes you'll deviate a weight from straight up rest since that's what the setup will require one more thing you can probably notice something essentially our api allows our user to perform a crot operations on our data and crud stands for create read update and destroy and it's a common approach where the api interface is built around crud since those are usually or typically operations that users or apps want to perform on a given data whether it is again users orders customers or in our case of course it is going to be a task and we'll return to credit a little later when i can actually show you how it relates to our data lastly there's obviously more to rest and some of that we will discuss in later projects but since i'm not a big fan of long slide videos and i believe we covered all the major points we'll stop right here and move on to our database setup if you remember in express tutorial the route setup was extremely similar to that we have right now with one big caveat we used basic array to store some list of items on our server and based on the request we performed some kind of operation on the list and then send back the response and of course that is not very serious approach to store our data and therefore starting with this project we'll set up and connect to a proper database and pretty much for the remainder of the course we'll use nosql or non-relational database by the name of mongodb now i'm not going to dwell on differences between non-relational and relational databases as well as pros and cons for each of them but the major difference is that unlike traditional database where we have rows and columns in mango divi we can simply store everything as json and basically it doesn't care how the data relates to each other instead of tables we have collections which represent group of items and instead of rows we have documents which represent single item and a document is a set of key value pairs and as far as data types we can use strings numbers arrays objects and many more it's very easy to get started and even though you can set it up on your local machine as well we'll right away go for cloud option since that's something you'll probably end up doing anyway we'll use mongodb atlas which is a official option basically it's created by the same people who created mongodb and since they offer generous free tier you'll just have to create an account and you'll be good to go and once we're familiar with mongodb let's set up and configure mongodb atlas so we can host and manage our data in the cloud i have the account already but since i want to cover all the steps in detail i'll set up another dummy account together and remember we can set up the entire thing for free so don't worry your credit card can stay nicely tucked away in your wallet if you get stuck or confused in any of the steps we're about to take here's an awesome resource you can use just google create mongodb atlas and follow this link which actually brings us to official docs and here you'll find a checklist which we're going to use as a roadmap for the following few videos and what is the first thing they want us to do create a new account so let's do this people i'm going to open this up in new tab and then of course you can find bunch of useful info in here yadda yadda you keep on scrolling and i actually want to navigate to a login page and i'm just going to pretend that i don't have the account and we're going to go for sign up and here of course you just need to provide all the necessary info and once you have filled everything out and as i said no don't worry this is not my real phone number then of course just click on sign up and up next they're going to ask for organization and project name and in my case i'm gonna go with node and express course then i'll pick javascript we'll click on continue and we probably can actually skip this but let's just leave it there and up next they want us to set up the cluster now if you take a look at the checklist actually cluster is already second step so let's go back here and pretty much you always want to show for a free one unless of course you want to start paying them so in here we'll just go with create cluster that's going to be the free one then it's using aws okay awesome as far as region i'm going to go with this one then we have cluster tier and additional settings and we'll leave them both as default and lastly i just want to change the name and i think i'm going to go with node express and project and once we're done we just need to click on create cluster and we'll get ourselves a new cluster now as you can see over here they say that it's going to take a little bit of time which is usually the case so i'll stop the video here and i'll see your next one where we'll continue with our steps and once our cluster is ready to go before we start messing around with data so with collections and documents and all that there's a few things that i want to do first and i'm going to start by setting up the database access so effectively in here we'll set who can access our database now i'm not talking about the atlas account no i'm talking about the database and collections we're about to set up and we simply need to click on add new database user and we're gonna go with password and if you get some default values just wipe them clean and i'll simply go with john and as far as the password i'm just gonna go with one two three four please please please do not do that in your own setup the only reason why i'm doing that because you'll be able to see my password anyway and don't worry once i'm done setting up this project of course i will change my password so it's not going to be one two three four and once you're done with the user and password notice we have database user privileges and this user can read and write to any database so i'll leave it the way it is and we'll add a new user that's good i'll close this one and then we want to set up the network access so we want to set up from where we can access our database and you can already imagine that of course once we deploy the project then of course we'll set up that ip address but for time being while we work locally we might as well set up access from anywhere now if you want you can set up your own ip address here so you can just add the current one but in my case i'm going to go allow access from anywhere and i'll just click on confirm and lastly i want to get the connection string that we're going to use once we connect our database to our application and in here what you're looking for is connect so you want to go back to the cluster then connect and then you want to go with connect your application so not the compass one not the shell actually the second one here connect your application and then i'm gonna go with 3.6 or later that's about right and then you just want to copy this one and then navigate back to our project now eventually we'll set it up as the environment variable yes that's going to be the case but for the time being i'll simply create a new folder in the starter and i'll call this db and then instead of the db there's going to be a new file and we'll call this connect gis and then i want to create a new variable and i'll call this connection string and i'll set it equal to that value now we'll have to add some values over here but we'll do that later once we're actually ready to connect our application to the database so just take the string copy and paste set it up in the db and then connect js and now we can start exploring the atlas setup as a quick side note while working in local setup essentially while working on your computer you can use any of these two options so either access from anywhere or our actual ip address but once we go to production more specifically once we deploy our project to heroku you will need to use access from anywhere option otherwise you'll get an error and you won't be able to connect your app to mongodb now this is specific to heroku for example when it comes to digitalocean another popular option for hosting your node apps if you're using your local address while developing once the project is hosted you just swap the ip address from local to production but the way heroku setup works you'll need to go with allow from anywhere option otherwise you'll get an error and once we have set up database access network access as well as the connection string now let's actually explore the data part and we want to click on collections then we're going to go with our own data and then we need to come up with a database name now the first one will be a dummy one and of course once we connect to our application then we'll create a task manager one so the first one i'll just call store and then they ask us to create a collection and don't worry i'll cover what actually our collections and all that but for time being i'm just gonna go with product and then we'll create one and once we have everything in place we are ready to start creating documents so whenever we talk about mongodb we'll have the database so that essentially is going to be that application again in our case eventually this will be the task manager one and then inside of that database we'll have collections now if you're familiar with regular databases you can think of them as tables and in our collections we'll have group of mongodb documents so if i name my one products you can probably already guess that here i'll have list of products and if i'll decide that my store will also have users of course i can go here and create a new collection and as a quick side note we won't have to do this manually i'm just showing you the general setup manually of course eventually all this is going to happen automatically once we connect from our task manager so i have a list of products and then of course i can also create a list of users or list of orders and hopefully you get the gist and once we have our list now let's talk about the individual items so i can go to any of my collections and then once i'm here i can insert a document and document in mongodb effectively represents that one single item and what's really cool that just like javascript object effectively it's a set of key value pairs now by default the moment we create a new document we'll get this underscore id which is going to be that unique id so we don't need to worry about the ids and then of course we need to set up a type so what is going to be the type for our document what is going to be type for the item and if you click over here as you can see these are options we can set it up as an array binary boolean and yada yada and i'm purposely not going to spend too much time on types since eventually we'll set it up from our server anyway and at that point the setup is going to be a bit different since we'll use tool called mongoose now in our case what are we looking for well we're just looking for the string i'm just going to go here with name and then i'll set it equal as first and product so here of course i can insert and now not only i have the product collection but i also have my first item my first document and here comes the biggest gotcha in mongodb documents have a dynamic schema and what that means in plain english is the simple fact that documents in the same collection don't need to have the same set of fields or the structure so if i were to go to insert document and instead of string i'm going to go with array and i'm going to call this colors and then i'll set my first one to be red then second one blue and if i'll save it as far as mongodbe is concerned they're still the same items in this product collection so nothing stops you from doing that now just because you can does not mean you should and therefore we will use additional library by the name of mongoose which will set up that structure for us but as far as straight up mongodb yes both of these documents are still part of this product collection even though their structure might be totally different few videos ago while discussing arrest i mentioned crud create read update and destroy or delete and now i want to quickly show you how is that going to look like with our current manual setup i fully understand that some parts might look really silly especially the read one but in my opinion it's important we start with the basics and hopefully that way we'll have a better understanding of overall principles when we need to implement crud in our rest api so what does crud means in our manual setup well first we want to create an item correct so in here we just find any of the collections and in this case i'm going to stick with products since i already have some items over here and then we simply go with insert document and again we just come up with a type and then some kind of value and my case i think i'm gonna go with another name and i'll just leave it as a string and i'll say test crud i'll insert the document and i'm done so we're done with the first part where we created an item now the second one reading them well we simply stare at the screen and we can see that we have three items so i can see that i have three products again in our application that just means that we'll be able to read the documents that we have in our database when we're working with gui it's very straightforward where you're just staring at the screen then we want to update them and then with the manual approach we just look for this little pencil and we say that we want to change some values around here so in here i could go with another item and i'll say green so now of course i have successfully updated the array as well and you know what let's also add one more and i'll call this orange then i update and i'm done with that part as well so not only we can create read but we can also update and then last one delete well we simply look for another icon in this case we are looking for the trash icon so we just click here and now of course we remove the item so that's the basic approach of crud in our manual setup all right and once our database is ready to go now we need to connect to it from our server and we can definitely use the native mongodb driver and i believe the package name was just that mongodb but a very popular alternative is to use package by the name of mongoose instead which is a object data modeling library and essentially the reason why it's so popular and why we're going to use it in this and rest of our projects is because right out of the box it comes with bunch of goodies that make our development faster now i'm not going to list them in this video since you'll see them in action in all of our projects just let me repeat that yes you can set up your apps with just native mongodb package but the reason mongo's is so popular is because it has extremely straightforward api and it basically does all the heavy lifting for us when it comes to our project i already installed mongoose so we can start using it right away but if you want to use mongoose in your own future project the command is npm install and mongoose and one last thing in this project we're going to be using mongoose version 5 something so if by the time you're watching this if they have a higher version pretty much everything starting from six so if you have five point i don't know 14 15 or whatever you'll be still in good shape but if by the time you're watching this they already have version six their api might also be different and at that point you have two options install this particular mongoose version or just use the latest one and utilize their docs as a quick sign note since i recorded the course mongos did come out with new version version number six now the good news is that as far as i checked the only change that affects our project is the lack of deprecation warnings which we're going to cover in the next video rest of them don't really affect us now i still suggest using mongo's version that's already installed in the starrer while working on these projects but as far as i have tested and the current student feedback you'll have no problem implementing the knowledge in your own project with version 6 instead all right and once we're familiar with mongoose let's kick it up a notch and finally start using our database on our server and the first thing we need to do is to set up a connection and at least a basic setup is going to look something like this where we're going to import mongoose and of course we're going to do that in connect.js so i'm looking for db folder and then more specifically for connect.js and then here at the top above the connection string i'm going to go with const mongos that's the name of my instance and then that is equal to require and of course i'm looking for the markers and once i have the instance then the method name is connect so we go here with mongoose.connect and the first thing we want to pass in is the connection string but if you remember i said that we'll have to make some changes take a look so this is going to be my username correct but then what is the value for the password of course that is some dummy value so in here we need to pass in our actual password so in my case of course that is one two three four but i strongly suggest using more secure one for your application and then here at the very end we have my first database so this is what they set up by default and that's going to be the name for the database if i don't change it and you're probably wondering well wait a minute i mean we didn't set this up on the atlas so why it's here you see if it's not going to be there it's going to be created for you so here you have two options either you can just go with this one or in my case i'm going to remove it and again just make sure that you don't remove more than you should so you want to remove everything starting with the forward slash all the way to the question mark and in here of course you need to come up with a name and in my case i'm going to go with the same name as my application so since i have 0.1 for no tutorial and then task manager is 0.3 that's exactly what i'm going to set up over here so i'm going to go with 0.3 then hyphen and i think i'm going to go uppercase so i'm going to go with 0.3 task and manager again this is going to be the database name and if you haven't created that database already they will create for you and once we add these changes our connection string is ready to go so now we simply need to pass in as a first argument now the second argument is going to be options and effectively this is where we'll pass in some values just to avoid some deprecation warnings and you'll see what i'm talking about in a second but for time being we'll just leave it empty and then this returns a promise so we simply can go with dot then and since i want to see whether i'm successful as far as the connection i'll just pass in the callback function and i'll say log and of course i'll remove the semicolon and i'll say connected connected to the db dot dot and then since there might be an error as well we also want to go with catch and of course we'll just be looking for the error so we have our callback function and i'll say error and we'll simply cancel log the error so we'll say here cancel log and i'm going to be looking for the error and once we save nothing happens and the reason why nothing happens is because we're not executing this function yet but if you remember during tutorial one of the first things that i covered is the fact that if we have a function in a module where the function is effectively executed there and then we only need to import meaning require the module and will right away execute the function so i simply want to navigate to app.js and then this is just temporary because we will change this setup around this one we won't leave it this way i just want to get the connection up and running and therefore i'm just going to go to app.js and then we go with require and notice i'm not assigning this to any kind of variable simply go with require then we look in the db and then more specifically we're looking for the connect and once you save you'll have tons of deprecation warnings and don't worry we'll fix them in a second but all the way in the bottom if everything is correct over here if you pass in the correct password and you grab the correct connection string then you should see connected to the database and if i want to test out the error i'll simply remove the four since i know that that is going to be a wrong password so once i save now of course i'll have this error so i'm just going to keep on scrolling and notice here it's going to say atlas error and of course i already know why because my password is correct and if we'll take a look at our graphical interface in the atlas once we refresh we're not going to see any changes because again we haven't set up any kind of logic so you're looking at it you're like okay i still have one database what's happening don't worry once we start adding the items that database will be created for us in my case 0.3 task manager and even though i will refactor this in the next video because there's some gotchas that i want to talk about before we do that i'll show you how we can remove those deprecation warnings in a console and if you remember we just need to pass in the second argument which is going to be an object and in here we just need to pass in following key value pairs and we'll start with use new url parser and we'll set it equal to true then we'll look for use create index we'll set that one equal to true and then we'll go with use find and modify that one will be false and then lastly we want to go with use unified topology and that one will set equal to true so once i save now i don't have any of those warnings i simply see server is listening on port 3000 and then i have connected to the database and if that is also something that you see in a console you are in good shape and we're ready to move on to the next step nice we have successfully connected to the database and life is great but before we start messing around with the data there's something that's bugging and simply the fact that our server and database connection don't work in sync now what do i mean well let's take a look at the console so first i have console log that our server is listening on port 3000 and only then we're connecting to the database but if we think about it what is really a use for our server if we are not connected to the database whatever we're about to do is going to fail anyway so what i'm trying to say is wouldn't it make more sense if we try to connect to the database and only if we're successful then we spin up the server if not well then we'll just kill the application and in order to do that we need to restructure our code a bit where i'm not going to invoke mongoose connect in the connect.js i'll refactor the code and i'll set it up as a function and instead we will invoke it in the app.js and in order to do that we'll just remove this dot then and catch now options of course stay we're not doing anything with that and here let's create a function we'll say connect and db and that is equal to our function so essentially we're setting up the arrow function and eventually we'll set up the env variable and effectively we'll pass it from the app.js and therefore i'll add the parameter here the url for time being we won't use it we'll do the same thing what we did before where we just passed in the connection string that's coming up in next video and then i want to grab this mongoose connect cut it out and then from this connect db i just want to return that result so effectively what we're returning we're turning a promise correct and then all the way at the bottom we're going to go with module and export so now of course we want to export it and where we want to export of course connect and db so once we have this setup then we'll just have server is listening on port 3000 because now of course we want to assign it to some kind of variable and again the order is really up to you but i'm just going to put it below the task so i'll just move it over here below the tasks and i'll say that that is equal to connect db so effectively i'm just getting that function over here and i'll set it equal to the required one and then once i have access to the function then all the way in the bottom i want to set up one more function by the name of start and in this function we will invoke connect db and then only if we're successful then we'll spin up the server so let's go somewhere here in the bottom and we'll say can't start again we'll use the arrow function and since i know that my connectdb returns a promise correct i can set this function as a sync and that way of course we can use the await keyword and every time we have a synchronous operation it's very useful to set it in the try catch block so that way if there is an error we can handle it as well and in try block we'll pass in a wait so since i know that it returns a promise i'll use my await keyword then i'm going to go with connectdb again eventually we'll pass in the string coming from the env file for time being we just have hard coded e and d connect js and then only if we're successful then we'll spin up the server so i'll move this line of code right below the connectdb and again we'll just spin up the server if the connection is successful if not we're gonna go with console.log and then we'll just look for the error so once we save nothing happens we don't spin up the server because of course now we have a function so all the way on the bottom i'm just going to go with start and then you'll notice that there's a console log for the server now of course we don't have the console log for the connection because we removed that in connect js but if you really want to test it out again go back over here and just mess with your password and you'll right away see that we'll get that error in console and in here it says bad auth authentication fail so we know that our setup works so if of course we will have a wrong password then we won't be successful however if everything goes smoothly then we should see that our server is listening on port 3000 not bad not bad we have set up the connection we have refactor code and we're almost almost almost ready to start tinkering with the data but there's one last thing that i want to do first and that is simply setting up the dot env file now why we would want to do that well let's think about it eventually we might push this up to the github correct and what do you think is going to happen the moment i push this up to the getup of course everyone who takes a look at my repo can nicely grab the string and then tamper with my data and how we can avoid that well the solution is to set up dot emv file where we can keep our secret and then in our application we'll have to use a package by the name of dot env and of course i already installed it for you and then we'll be able to access those secret variables anywhere in our application and once we push this up to the github if we add git ignore so dot git ignore file and then in here we specifically say which files we want to ignore and make sure that you add dot env now i also added node modules because that is common practice since that folder is so big but as far as keeping secret secrets make sure that not only you set up dot env and of course use the package because otherwise you won't be able to access the variables but always always always the moment you set up dot env also set up dot git ignore and that way we'll just push this up to the github and then dot env will be ignored so when people come and see your repo they won't see this secret connection string so let's start here by creating dot env and in my case i'm going to do that in the root so i also suggest you do the same so i'm going to go to the starter i'm looking for new file and i'm going to go with dot and then env and in here we have again key value pairs however we don't need to use the quotation marks and i think i'm going to go with and then uri in this case so i'm not going to go with long name the connection string and then you simply want to take this value so cut it out from the connect js go back to dot env set it equal to my uri and then where i have connect js i can simply remove it and then remember when we were setting up the function i said that i'm going to be looking for the parameter but of course initially we were not using it now of course i want to use it so i'll remove the hard-coded connection string and i'll say url and we'll just save now there's going to be an error don't worry because of course we're not passing that connection string notice over here we have the parameter blah blah blah is undefined okay that was expected now what we want to do is go to the app.js since over here we invoke start and then we want to pass in that value from the dot envy into the connect db and in order for us to access those secret variables we simply need to require that package so i'm going to go below connect db and we'll just say require and notice how we don't have to assign it to any kind of variable we just go with dot env and that's the package name and as i said if you want to install you just go with npm install and then the package name dot env pretty self-explanatory and then you want to use process dot env and then whatever is the variable name so let me save my dot env and then back in the app.js once we require we just want to go with dot and config so essentially we just want to invoke the config so now if we keep on scrolling where we have the connect db we want to go with process dot envy and remember that was one of those global variables we go with dot env and then we go or whatever the name for your variable is in my case that is uri and we'll save it and of course we're back in business because i have server is listening on port 3000 again very very important if you want to keep your secret variables actually secret set up the dot env get the package and you'll be able to access them anywhere in your application by using process.env and then whatever e is the name of the variable beautiful and once our connection string is a env variable now let's set up the structure for our future documents and assign them to the collection and we're going to do that using schema and model from the mongoose and the way it's going to look like we're going to go to our starter and we'll create yet another folder and in this case we'll call this models and then inside of the models we'll create a new file and we'll call this task.js so i'm going to go here with task.js and then the setup is going to be following where again we import mongoose and we set it equal to require and then mongoose of course and then we're looking for mongoose.schema so we set up a new variable and i'll call this task schema schema and that is equal to new so we're using the constructor and we go with new mongoose and schema and you're probably wondering okay what on earth is happening well if you remember when we were setting up the atlas manually one of the first things that i mentioned is the fact that for our document there is no set structure but that's exactly what i want where for my tasks i only want the name which is going to be a string and a completed property which is going to be a boolean because you would have to agree that it's not going to make much sense if somewhere in my tasks i'll have an array with the color values correct so therefore we go here we go with schema and using schema we'll set up the structure for all the documents that eventually we'll have in our collection and the syntax is following where again we use key value pairs and eventually we'll set them equal to an object and we'll pass in more options but since i just want to get something quickly in our database we'll just start quick and dirty where essentially i want to come up with a key in my case again that is going to be name and completed so those are going to be the two keys and i'll just set up the types so that is a bare minimum where you go with the key name and then the actual schema type so what type of data this is going to be and if you're interested on what options we have just navigate to mongoose official docs and then look for schema types keep on scrolling and then of course you can see string number and yada yada so i'm going to navigate back and i'll say name so that's going to be my first key and i'll just set it equal to string then comma and of course i'm looking for completed completed that is going to be my second key and that will be set equal to boolean again barebones setup will do more complicated a little bit later and then once we have the schema so essentially once we have the structure for the data now we want to set up that model and think of model as a representation for the collection so these guys are sticking in the product so now of course we'll create tasks collection and then all the tasks that we're about to push into our database of course will be added to that specific collection and what's even more cool in mongoose a model is a wrapper for the schema so if the schema defines the structure for the document like the type validations and etc a mongoose model provides an interface to the database so using the model will be able to create update query and delete our documents with great ease since the api is extremely extremely straightforward and you'll see what i mean in the upcoming videos and we do that by creating a model and we right away export so go with module dot exports and that is equal to mongos then model and then model is looking for two things it is looking for the name and then we want to pass in the schema so in here i'm going to go with task and then comma and of course this is the schema that i want to pass in so say here task schema and once we're done with this the only thing we need to do is go to our controllers and start using our model beautiful we have set up our first schema as well as the model and of course we want to start using it and yes we will use it in controllers therefore we'll navigate there and i'm going to be looking for my model and i'll assign it to the task variable i'll say require i'm looking in the models folder and then more specifically task and then before we continue let me just give you a brief overview of what we're about to do so if we navigate back to mongoose docs and more specifically if you're looking for the models we can find here more info you can see that models are fancy constructors compiled from schema definitions an instance of a model is called a document and then they give you this example pretty much everything that we did in last video apart from the fact that of course they have different values and here we have nice explanation that the first argument is singular name of the collection your model is for since mongoose automatically looks for the plural lowercase version of your model name so effectively eventually we'll have the tasks then i mentioned one more time that the instance of the model is called document and there are few ways how we can create one we can go this route or we can use dot create and here they showcase the callback function approach but we can also use a weight and essentially what create is looking for well it's looking for the object with those properties so in our case we have name as well as the completed correct and of course we can pass this manually but wouldn't it make more sense if we just go to create task route and since we know that in there we can access the task data in the request.body why don't we just pipe it through and pass it along to our model create method and it's going to work something like this where i'll grab the body of course it's going to be coming from my postman here shake and break and the value will be true and then instead of sending it back we'll pass it into task dot create now since i'm going to be using a weight on a task dot create of course i want to refactor this and i'll say that this function the create task actually is going to be async so my controller will be async and then instead of the function body i'm going to go with task and i'll set it equal to a weight like i said i'm not gonna use the callback function approach i'll use a weight instead and we'll await for task dot create and like i said if you want you can hard code this here you can say name and then first task and of course we can do the same thing for completed but i already covered why it's going to make way more sense if we just take this rec dot body so whatever we're getting from the postman and then let's just pass that object into task.create and let's see what happens so i'll remove it here and i'll just say rec dot body over here and as far as the response well now i'm just waiting for a task so instead of wrecked that body in response i'll place my task and i also want to add the status and if you remember the correct status was 201 effectively that is if you have a successful post request and then instead of json being equal to rec.body we'll pass in the object and in here we'll pass in our task and then once we save again nothing happens because we haven't triggered the post request but if we go back to the postman and if i click here send what i should see is this i should see the task so that's my object and now check it out we have this underscore id and what that means well that means that we created a new document with the following properties we have name we have completed we of course have the id like i just mentioned and we also have this underscore underscore v so of course these two are created by default every time we create the document and then these ones we provide so if you want to keep on testing we're gonna go with second task and we'll set maybe the completed to false again this is all quick and dirty just because i want to have some data in my database there will be still some modifications to the code but if we can see the successful responses where we have tasks with underscore id what that also means my friends is that when we go to our database and if i refresh check it out now of course i have the task manager like i said that's my database and what do you know of course i have the tasks collection now what do i have in task collection i have documents what documents shake and bake and second task and if you have the same result congrats we're off to the great start nice at this point we can successfully create new tasks and persist them in our cloud database so now it's really just about applying the same concepts to the rest of our routes but before we set up the rest of the four controllers in a similar fashion there are a few important things that i want to cover first for starters i just want to showcase that since we set up our schema only the properties that we specified in our schema will be passed on to the database and everything else is going to be ignored don't believe me let's try it out first i just want to showcase that in our schema we specified two properties name and completed so now if i go back to the postman and i'll just set up testing schema that's going to be my name testing schema i'll leave completed as false but if i try to add some properties that are not on my schema effectively they will be just ignored so my guys i'm just gonna say random is equal to random now i do still need to use the proper jsons index and then i'll just add the amount and i'll set it equal to five now you can add 10 000 properties and again the result is going to be exactly the same so i'll just leave these two and we'll try to send it so here i send and then check it out now what i get back is only the name and only the completed again let me repeat only the properties that you set in your schema will be passed on to the database everything else will be ignored which of course is really really cool because that way we can avoid this mess where if you remember back in the store when i was setting up the products one has name the other one has the colors because there is no structure for these documents when we use schema there is a structure so whatever we set up in a schema is going to be passed on to this database and whatever comes as an extra is just going to be ignored all right and once we've got that out of the way next i want to talk about validation you see even though we only accept the properties that are specified in the schema our current setup has one big doozy there is no validation so essentially we can pass in empty values how is that gonna look like well again we can go back to the postman and in first example i'll just remove completed and i'll pass in the name as an empty string now i do need to fix this comma here but you'll see that actually we're successful so i can create item this way and what's even more interesting is that i can send an empty object and i'll still be successful and you have to agree that actually this is not the best setup correct so that way we can just set up a bunch of empty items now what can we do about it well we can add the validation to our schema now before we continue though let me just say that when it comes to validation since it's a pretty big topic we'll just be scratching the surface the plan is to show you more features as we progress with the upcoming projects since i have a feeling that if we'll spend the next hour or two on just validation understandably a lot of you will lose interest and attention don't worry though the end of the video i will show you where you can get more info so at the moment we have a very minimal setup where we have properties and we just specify the type however we can set up our properties as objects and then we can also set up built-in validators how is that going to look like well i'll remove the string part from the name and then i'll set it equal to an object i'll add a comma of course since i need to keep the proper syntax and here the first property we want to set up is type now it's still going to be a string but now of course we can add more validators now what validators can we use for starters we can go with required so what this is going to do is if i pass in the value the object without my name property then it's going to spit back big fat error now at the very basic level you can set up equal to true or false either it is required or not but if you want a custom message you can actually set it equal to an array where you go with the first value again true or false and then you add a comma and then you pass in that custom message and in my case i'm going to go with must provide and name now what else i can do well i can trim to imagine the scenario in a postman if i go here with name and if i pass in here spaces and then john effectively with our current setup that's exactly how we'll save it in our database and if i don't want that i can simply go back where we have the object and then the property that you're looking for is trim and we'll set it equal to true and what's also really nifty that for strings we can get min values or max values and in my case since i don't want my value to be bigger than 20 characters for the name one i can go with max and property that we're looking for is length make sure that you spelled correctly this is always a doozy for me when it comes to length and again we'll set it equal to an array and i'll say that the value for my string is going to be 20 and then in here we'll just go with name cannot be more than and of course we'll set it equal to 20 and nine characters and essentially we're done with basic validators for name because like i already mentioned i really just want to scratch the surface so you get the main idea and then as we're progressing with the project then of course we'll implement more features and i want to do the same thing for completed where i'm not going to go with required hopefully this is clear and you'll see in a second what kind of error we have if we don't pass the name but for the completed i just want to show you that we can also set some default values and again we want to remove this boolean and we're going to go type we'll set it equal to boolean and then as far as the default value the property is simply default and as far as default in this case for the task property completed i think it's going to make most sense if we'll set it equal to false again just to showcase how is that going to look like in a real project so as i'm adding the task new task by default it's not going to be completed and only when we navigate to a specific task page and i say yep it's completed now we can add it and then of course we can navigate back to all the tasks this was just my setup of course there's a million different ways how you can do that but that's why in here when i'm setting up my validators i set my completed one to be equal to false so now of course we can save it and we can test it out so i'm going to navigate back to my setup here in a postman and as you can see completed is still not required and that is done on purpose so essentially i already set this up as default false so i don't want to set it up as required therefore we don't need to pass it here but i just want to see how it nicely is going to trim and how we also will get errors if we don't pass in any values so in here let me just try with the john and notice once we send we actually get trimmed value back and completed is set to false right away okay that's an awesome start but notice what happens if we send an empty string so let me remove all the values let me click on send and now check it out so we have here this sending request and the reason why we're not getting anything back because we have big fat error in our console we have validation error and there's few things that we need to understand about this error first it is caused in a task schema because we finally set up the valve there and we set it equal to true and of course we're sending empty string so that's the same thing as if i were to send completely empty object over here so if i cancel it and if i send it again notice again we're not getting the response that's point number one number two if you take a look at the console you see that we have this unhandled promise rejection and this error is originated blah blah blah blah and long story short it is caused in our create task because we have a weight keyword however we're not handling this gracefully we don't have the try catch block where we set up the await in the try and if there's an error then of course we do something about it and since this video is already getting quite long i'll actually do that in the next one so just put this one on ice and then in next video we'll set up a proper response and just to recap as far as basic validation we just need to set our property equal to an object then we need to set up still the type and in our case that was the string and then we can go with the required if we want to have a custom message then we just set it equal to an array and the first item is going to be the value whether that's true or false for required and then the second one will be the custom message then for the string we can also use trim and that's just going to make sure that we don't have any white space and you can probably already guess that there's one for the min length as well and in a completed one we covered how we can add a default value as well so for this one we set it equal to false and if one of our validations is going to fail then of course we won't be successful of adding that item and like promised if you want to learn more about validation just head on over to mongoose docs so navigate here and then you're looking for the validation and as you can see there's quite a bit of info here so if your idea of good time is scouring through the docks you won't be disappointed not bad not bad i think we have good general understanding of the basic validation in mongoose so now let's switch gears and talk about how we can handle it more gracefully because at the moment well we're just leaving our user hanging correct so if the user sends some kind of request with incorrect data then of course we have the error here on the server but as you can see the user is just hanging and probably it's not the best approach and again the whole reason for that is because we have a synchronous operation however we're not handling if there is an error and the fix is following where we want to go with try catch and then we want to place our await in the try block and also right away set up my response so if we are successful i still want to send back the response with our task document the one that we're getting back from the model and then the second thing if there is an error what do we do well we could also send back the response and in this case the status is going to be 500 and effectively that is just a general server error and as i said i'm purposely using just a general server error status code the 500 one since we'll discuss errors in greater detail later in the project and then we can go with json and i'll set up the message property and i'll set it equal to my error so now if we save and if i go back and if i send one more time you'll notice that instead of hanging we actually get a response and in here i can see that the status is 500 so it's definitely our response and at this point in time you probably have two questions first do we really need to wrap all our logic in every controller in trying catch since i can give you a hint that in the remaining controllers we'll also use the functions and we'll stick a weight in front of them and the short answer is yes for timing we'll have to do that but then eventually by the end of the project i'll show you multiple ways how we can simplify that and how we can omit this boilerplate code for try and catch then your next question probably is okay we get the response but this error seems a bit lengthy can we make it shorter and my answer again is yes we can and the most basic approach is going to look something like this instead of setting message property equal to another parameter just simply set it equal to generic there was another string value as far as more complex setup i'll discuss it at the end of the project since i want to keep moving along with the rest of the functionality as far as my setup i will keep sending this giant object since that way i can show exact error messages we're getting and as far as our api i think we're actually in pretty good shape where we can create a task we do have some basic validations and if there is any kind of error well we simply send back 500 that there is a server error and we send back error message yes quite long one but at least it's better than leaving the user hanging and if we want to try out the max length and simply go here with name and then i'll just add some gibberish just so it's more than 20 characters so let me type it out here and then once i save again we get the error message where we have name cannot be more than 20 characters that should do it for this video and now we're ready to move on to our next topic and once we're done discussing the validation as well as the need for try and catch since we have a synchronous operation why don't we continue with our controllers and up next i want to work on get all tasks so we know already how we can create a task we know that we have a model in the model we pass in the schema and then in order to get the instance we go with the name of the model and of course the method name is dot create now what about rest of the correct operations and again we'll use our best helper the mongoose docs and if we navigate there and then if we look for queries then we can have this nice text where it says mongoose models provide several static helper functions four and this should be already familiar crud crowd operations and each of these functions returns a mongoose query object now we'll work with query object way more in the next project but for time being we just need to understand that on every model we have these methods that we can use starting with delete menu all the way to update one and the one that we want to use right now is this one the find one and i'll just open this up in a separate tab and then we can see that as far as the parameter we want to pass in the filter object now what does that mean well it means that if i'll leave this filter object empty this is just going to get me all the documents so in our case this is just going to get us all the tasks now if we start supplying the values for example in our case we could say completed equal to true of course that is going to get us what that is going to get us only the documents that are completed again the way i've set up the projects of the next project the second project is the one where we'll take a deep dive into the filtering sorting and all that for time being we just need to understand that if we want to get all the documents which is going to be in our case for the get all tasks controller we simply need to use find now it's also really interesting is the fact that if we go back and if we keep on scrolling we can read that a query also has dot then function and thus can be used a promise now there is a caveat where technically it's not returning a promise that's why i say here used as a promise and essentially what that means for us is that yes we can use a weight so for simplicity we can stick a weight in front of it and we'll be in good shape however if you keep on scrolling you'll read that queries are not promises and there are situations where it's really important but if we keep on reading here they have that then function for async await as a convenience so long story short similarly to how we created task with a weight and we set up try and catch block we'll do it here as well and the way we'll do that we'll go with try catch so in here of course there's going to be an error but if we're successful then of course we'll just send back all the tasks so let's start here with const and i'll set it equal to the tasks and the value will be equal to a weight so use a weight keyword therefore in front of the function i want to set up my sync and then i want to go with task so that's going to be the name of the model and then the static function name is fine and since i want to get all the documents in the task collection therefore i'll just stick here a empty object and then as far as the error well in order to speed this up i'll just copy the error from the create task and pass it here as well and now the only thing is missing is our response if we're successful what do we want to do well we want to go with res dot and then we're looking for the status in this case the status is going to be 200 and then json and in here i'll just say tasks so i'll be sending back the object and then instead of that object there's a property by the name of tasks and as far as the value it's going to be equal to whatever i'm getting back from the find and i'm just using the es6 shorthand where if the property name is exactly the same as the variable for the value well we can omit the second part and effectively it's the same as if i were to write like this so we have tasks equal to tasks and then with es6 we can just shorten this up and once we save and if we go back to the postman and you know let me fix this one i'll say here properly i'll say testing testing task because i want to save that create one so i'll save it here so it stays as our request and i'll close it and then if we go to all the tasks and we simply hit send now what we should see is of course our object and check it out now we have all the tasks so we have our array and then inside of that array we have items of course each item is represented as an object so successfully we have set up the second route as well for all the tasks and here we use the find static function and we pass in the empty object which just gets us all the documents in the collection and in our case of course those are our tasks and then if we're successful if there was no error we just go with res dot status so we set up the status for response and we send back a json and i just jam all my tasks inside of the object and set it equal to the tasks property awesome and once we have set up the controllers for create task and get all tasks next i want to work on get task and effectively in our application that route provides info about specific tasks so in here i can see all the tasks i can create one of course but if i want to edit it i'm going to click on edit button and then notice how i'm getting the info about this specific task of course normally you wouldn't share the id but in this case i just wanted to provide more info so not just the name but also an id so that way you can clearly see that this info is just about this task and similarly i can go to the next one and again i'll get the id i'll get the name and whether it's completed or not now in this video of course we won't set up the edit but at least we'll get that specific info and general the setup is going to be pretty similar to the one we have with get all tasks however we'll also have to implement a specific response if the id that we pass in doesn't match any of the tasks that we currently have and in order to get up and running we'll navigate back to the docs to the mongoose docs and in this case we're looking for the find one static helper function just like we used find in this case we're looking for find one open up new browser window and then notice as far as the parameters we go with conditions so we pass in conditions object and they're very helpful here where they say find one adventure whose country is croatia otherwise no so essentially we use a weight just for convenience we have our model then we have find one and then we pass in the object and in that object we set up what well we set up the condition and in this case they look for the country in our case of course we will look for a task and we'll use the id so i'll say get me the task whose id is equal to whatever i'm getting from the params otherwise we'll get back now so let's now get back i'm looking for get task and remember in here of course i'm getting that params id and before we type anything here in the controller i just want to set it correctly my id because of course initially well i was just passing here repeater but of course that's not the case anymore and since i want to use the id that i'm getting back from the mongol i'm gonna go to all the tasks i'll run it of course i get my list awesome and then pick any of the tasks doesn't really matter which one just look for the id copy this one and then go back to the single task and then of course instead of peter pass in the eddy and send and if you get back the id key with this value with that long string value which is an id then of course we're in good shape and i'm doing this just so we don't have the console log here on the server you can definitely do so but i just think that it's more convenient for us to see those logs here in a postman and then once we have everything in a place i want to go with my get task and here what's the logic well we could start by setting up i sync of course because we'll use the await then we'll go with our try catch block and then i'll move this sucker up and then first we just want to get that id out of the params so of course you can write it the long way but i always like to do the structuring first so we'll go here with const id and then i always prefer giving it somewhat useful alias otherwise you just end up with bunch of ids and then once in a while it's just confusing which id is for what so i'll say grab me the id which is coming from the params but use the alias of task id from now on and then i set it equal of course to rec dot params so it's the same object that i'm getting and then of course we want to use that fine one correct so we're going to go with const this is going to be our document that we're getting back if we're successful and we'll go with await and then task and then find find one and then like i said we pass in the object and in this case i'm going to be looking for underscore id so not the name but underscore id which matches to that in the params so use here task and then id and if i'm successful beautiful we'll send back the task if not then we'll have to send back the 404 response so here we'll go with res dot and we're looking for status so say that everything is correct we were successful and therefore we'll go with res dot status 200 then dot json and then i just want to pass in a task i'll say yep that's the task you're looking for now there also might be a case where there's something wrong with an id where essentially yes we're getting the value from the params but it doesn't match any of the tasks and if you remember documentation then we get null so what is the case then well then i want to check if the task actually is null and then of course i want to send back different response now make sure make sure make sure that you always always always set up here return otherwise what's going to happen well javascript is going to be reading the code and if you don't have the return even though there might be no task well you'll send one response and then you'll send the next one right after that so always always make sure that you have return so that way javascript knows okay so now i just need to return from the function and in here we go with res.status now in this case though of course task that we're looking for doesn't exist and the status code for that is 404 and then again we go with json here and we'll pass in the message in the object and the message we'll be following we'll say no task with id and then colon and then we'll just look for task and then id and eventually of course we also might have the error and i'll talk about these two errors in the next video because that's going to be a common theme that will set up for the upcoming rounds and i kind of want to give it a separate video so in here let's just scroll up and let's just look for that generic one the arrest that status 500 and then we'll just pass in the error copy this one and then scroll down and below where we have the catch of course pass it in so if i go back right now to my postman and if i click on send i should get shaken big because of course that is the id now if you don't believe me we can go back to all the tasks let's keep on scrolling and then i think i'm going to be looking for this testing schema because some of them are actually empty when we were testing out that's when we were setting them up so now grab this id instead go back to single task and then copy and paste and of course now the value is going to be testing schema and like i mentioned previously i'll talk about errors why we have two of them essentially why we have two responses for the errors in the next video but that's how we can set up a route to get a single item so we go again with try catch we set up async and then we use the static function find one and then of course in this case we're looking for the id that has the value the same as in our params if we can find one awesome we send back that specific task if not then we send back 404 and then all the way in a catch block we have our generic error okay so why do we have these two responses where we have four or four with no task with this id and then we still have the generic one well it's simply because we can have two types of errors and in order to show you that we just need to navigate back to the postman and then notice where we have the params where i set up this long id why don't we try changing the last value so instead of b that i have here i'm gonna go with zero and once we send well we should get the message no task with blah blah blah id why well because of course in our database we don't have any item whose id is matching and i can clearly see the 404 that means that of course that that is our response but if we change this around and then instead of keeping the same amount of characters we start removing or adding you'll see this error and the name of this error is cast error so effectively what's happening if we have the correct syntax for the id but we cannot find the item then of course we'll have to deal with it ourselves because essentially there is no task with this id but if the id is actually going to have the wrong syntax meaning it's not going to match the amount of characters that mongoose is looking for then of course we'll get the error from the mongoose and like i already mentioned this is going to be somewhat common setup for us for the upcoming controllers as well because for both of them for update task as well as delete task at the end of the day we'll still have to find that one specific item and if we're not successful then we'll send back the 404 but we'll always have this generic one as well just in case the actual syntax for the id is totally off awesome i think we're moving in nice space and up next i'll actually work on the lead task why well because with update task it's a bit more complicated and i kind of want to leave it as the last one because i promised you that i'll show you the differences between put and patch as well so therefore let's work on delete now most of the stuff is going to be exactly the same so once you're comfortable with delete i think you'll have no problem setting up update tasks as well and just to showcase in our application if we go back to all the tasks if you click on removing the task there we go now of course we just removed the task and the setup is going to be very very similar to getting the task of course the biggest difference is going to be the method or the function that we're going to use and in this case we're looking for find one and delete but everything else pretty much is going to be the same so if you want you can just copy and paste and change the values but in my case since it's going to be a bit more productive why don't we type it out together so i'll go with my sync we go with try catch block now i have simple res dot sends so i'll just remove it all together then we want to look for that id in the params because again setup isn't going to be exactly the same where we pass in the id with our params and we'll call this task id and that one is equal to rec dot params then once we have access to params we just want to go with const task is equal to await again task and then find one and remove or i'm sorry delete so find one and delete and in here we want to pass in the id again so underscore id and that one is equal to our task and then id and then once we have the setup of course then we have two options if such task exists then we send back r200 if the task doesn't exist so essentially if this is equal to null then of course we go with r404 and in this case i will speed this up a little bit where i'll grab the if condition like so and then as far as the response initially i'm gonna go with a json object and i'll set task equal to task but at the very end of the video i'll discuss multiple options that we have so this is the 404 if we're not successful again if that item doesn't exist with that particular id if we are successful we go with res dot and then status and we pass in 200 and then we just go with json and then we pass in the task so essentially that way in a postman we'll be able to see which task we removed and then just like the previous controllers we'll grab our generic one as well and set it up in the catch one so if there is an error there's going to be a message property with that particular so we navigate back to the postman and we're looking for delete task again we have this dummy value in my case that is peter but in your case it might be something else so again we need to go to get all tasks run it so now of course we can see all our tasks and then just pick whichever you want to remove and you know what in my case i'm going to go for those empty ones first because i don't want them in my database anyway so i'll go over here i'll grab the id and then i'm looking for delete task copy and paste and then once i save check it out now of course i can see that i removed this task and i'll remove another dummy one as well so let me run it one more time now i can clearly see that i have only one without a name since i removed the previous one so let me just grab it over here and then back to delete task copy and paste and then send and of course i can clearly see that i removed this one as well and just to showcase again why we have those two errors let's go back to all the tasks let's send and i'll grab the first one for shake and bake and what you'll notice is that if i pass in the id and if i just change the last value so i still keep the same structure then of course we'll get our 404 so no task with id and of course i have 404 now if i'll start adding or removing the items and of course what you'll see is this error so of course this is coming from our catch block hopefully that makes sense and then lastly i just want to mention that as far as this response i purposely set it up here as a task just so we can see in the postman because i think it's a bit useful when we're setting up our first api but by any means you're not limited to sending this type of response why well because usually when it comes to deleting a task you're really not looking for the data here take a look at our front end it really doesn't care what task we're actually removing because the way the functionality works is i click on a button then i'm looking for a response and if the server sends back this 200 then right away on my front end i go like okay awesome i was successful so let me fetch the entire list one more time so it's not like i take that item and then i do something about it no i just say i want to remove the item if i'm successful awesome i'll do one thing if i'm not successful then of course i want to display some error message or something along those lines therefore if you go back and if you change this around to for example and i'll just show you some common ones that you might see in the other apis so let me comment this one out i'll copy and paste and then as long as you go with 200 you can simply even go like this you can say send that's it that's all you have to do and the functionality will still work or you might see something like this where again copy and paste and then if we go with json and some people just go with task and then set it equal to null and you might add a status property here with success and as you can see sky is the limit i'm just showing you what type of responses you might get back because again the main idea is that if you're successful if you're getting d200 already on a front end you know what's happening so most likely you're not going to be looking for that one specific item that you're deleting but again in my case i just set up this task so we can nicely see in a postman what we're moving so i'll remove these two lines of code here and then i'll just set it back to my json where i have task is equal to task and as a quick sign out once we're done setting up the update task route i'll spend an entire video on various options that you have for your responses so just put the pin on that and we'll come back to it a bit later all right and we have successfully arrived at our last controller the update task one and if we are comfortable with getting the single task and setting up the delete task we should be in good shape because yes there's gonna be a bit more functionality because in this case not only are we looking for the id but we'll also need the body since of course we'll be updating something correct and then the second thing we have to pass in some options since by default we won't get right away the validators working and also we won't get the item that we just updated and don't worry of course i'll talk about all of that in detail so for now just to stay consistent i'll move this sucker down i'll move it below the delete task and let's just start simply by accident both of the things let's get the params one and then the body one so we just want to see that we are successful on acquiring both of those things so i'll set this up as async it's just a simple send so i'll just remove it and we're going to go with try catch and for now let's just go with arrest dot and then status we'll set it equal to 200 and then the json one and here i want to grab two things i want to grab my id just double check that i'm getting it properly from the params and also the body so for now above the res dot status let's set up the id one more time we'll say id so we're destructuring from the rec dot params rec dot params and second one is going to be rec.body and if you want you can assign it to a data or whatever but in my case i'm just going to set up the property here and set it equal to directly so let's just say id is equal to a task id and then data is going to be equal to rec.body again why are we going to be passing data well because if we're updating something of course you need that new info correct so if i go back to my application and if i say that instead of walking the dog i want to walk the cat of course i need to supply this name otherwise it's not going to make any sense the same goes for completed i need to pass in that key with the new value and in this case of course it's going to be false so once i click edit notice i'm successful awesome so if i go back to all the tasks now i have lock the cat and in order to test this out again we need to go back to the postman we're looking for getting all the tasks since i want those correct ids and you can pick any of them doesn't really matter i think i like the shake and bake the most so take this one then we need to go to patch the update task one copy and paste and then in response we should see the id correct we're not gonna see the data since we haven't set up anything here in our body at least not right now but we'll do it in a second but of course now we're just getting update task so let's see let me go back here update task probably i didn't save the file my apologies let me run one more time and now i should see the id that matches of course my shake and bake but as far as data there's nothing there why well because i haven't sent anything from my front end right so now let's go to the raw and then we'll set it equal to the json and then we set up our object and remember we're looking for the name and i'll just say testing edit funk functionality i guess and then we're going to be looking for completed and we'll set it equal to let's just double check in here it's true so let's go with false and let's set it here of course now not only i'm getting the id just coming from the params but i also have the data property and in there of course i can clearly see those values again the whole deal why i'm doing this is just so we don't have to console.log on a server and once we have all of this in place now let's roll up our sleeves and actually set up our functionality so i'll remove this one we don't care about this one right now and again we want to go with the task meaning i'll sign up a variable with the name of task and i'll set it equal to await and of course now we're looking for task the model name and then find one and if this one was find one and delete what do you think is going to be this one well it is find one and update and in here we need to pass in a few things first we need to pass in the object where again we set up our condition so in this case again i'm going to go with id matches to that one in the params so underscore id equal to task id that's step number one then of course we need to pass in that new data since we're updating something correct so let's go here with comma and that's going to be the second value so essentially you need to set up the object and set up which properties you're updating but remember we're already getting that as far as wreck that body so reg.body is right away this object so i can simply set up my next parameter like so where i go with reg.body and then we have options object but i first want to show you what happens if we don't use it and then we'll add both of the values in there as well so let's start here again by checking the task because again we might have a situation where there is no task with that specific id and again just speed this up or copy and paste and then if we are successful then of course i want to send back the task i'll say task is equal to task and don't forget the generic error where we go to resdot status and then you already know the rest copy and paste and you'll notice something interesting since we don't have the options you'll notice the following thing where i go with testing edit function okay that's awesome i completed false but essentially what we're gonna get back is the original value so remember the shaken bag effectively this is what we'll get back so once i send notice yeah i get 200 so i was successful but notice the value here it's shaking big and what's more interesting that once i click on getting all the tasks it's actually changed so i was successful so here's the gotcha the reason why is that happening is because we're not passing in the options and as far as the options we want to do two things we want to get the new one back because by default we're getting the old one that's why we were successful but in our update response we got the old value and the second thing what you'll notice is the fact that we're not running the validators so if you remember when we were setting up the model one of the things that i set up for the name was required equal to true now if i try to update item with name equal to an empty string i'm actually going to be successful now again we're getting back the old value and in order to check the new one we just need to run get all tasks notice and i promise you i'll say this for the last time in this video the reason for that is because we don't have the options object and in order to set it up we just need to go back to all the controllers and like i said third parameter is going to be our options and then we simply go with new true so this will always always always return that new item the one that is already updated and then the another property we can run is run validators and we'll set it equal to true so once we do that of course we fixed both bugs so if i for the final time i guess in this video go back to my post man and in here i'm gonna go back to shake and bake and we'll set the value equal to true we should see that right away so i can see shake and bake and if i try to do that without passing anything in the name then of course i'll get my big fat error because when i was setting up the model i said that name is actually required awesome and believe it or not we're actually done with our basic setup as far as the api and in order to showcase that i'll simply go back to app.js and then i want to serve my static files because this is where my app is sitting and of course since our api is up and running we can simply set up those static files the app and the functionality should work and if you remember in order to serve static files we need to use another middleware and we're going to go with app.use we'll pass in express and the name is static and then in here we just simply need to say where the static files are located and in our case of course that is in the public folder and let me just say that if your code is exactly like mine everything is going to work now back in the app.js i don't think we need that hello one anymore so let me remove this one folder out i'll just leave the version one and then tasks and then if i go to localhost 3000 and i removed that hello i should see my app and i can clearly see that these are all the tasks that i currently have and if i want to add new one i'm just going to say testing app and once i add of course i have all the way in the bottom a testing app well effectively i have two but we right away can also practice on deleting so there it is now we can delete the items all the way to second task then if i want to see the single task just click over here notice now i have the task id as well as second task and then eventually if i want to edit well i just click here on completed and i'll say third task third task and if everything is correct we should see task edited now i still need to fix the css but as long as you see the correct text you should be in good shape now of course by the time you're watching this i'll fix this but the idea is following if i try to edit the item without providing the name now of course i'll get error please try again i just need to fix the css more essentially if i'm successful i still get this red color and then once i navigate back now these are going to be my task if you're interested in the actual app just navigate to the public one you'll see that i used vanilla.js just so everyone can be on same page and essentially as far as the logic you're looking for browser objects and i'm not going to show you the entire thing but as far as submitting the new task i'm just listening for submit event then i prevent the default i'm looking for the value in the input and notice that i'm using the axios library and check out the method what is the method name that is post why well because that's how we can pass data onto the server correct now what is the url that should be familiar we have api version one and then of course i'm looking for the tasks and in here i pass in the data so unlike the postman where we were doing that manually now of course i just grab the input and i'll pass it in and if you remember the completed was set to false right from the get go so i don't need to worry about that i just need to pass in the name and again everything is in try catch so if i'm successful then of course what happens well then i add the correct alerts and all that and then i just refetch one more time tasks now if i'm getting the error then of course i'll add different alerts and hopefully you get the gist and just to lastly showcase the delete one if we scroll up a little bit notice the method here and like i previously mentioned the only thing i'm looking for here is the response if everything is correct if i have 200 awesome i just refetch all the tasks if not then there's an error and essentially i don't remove it from my dom that's why i said that technically when you're set up for the delete in most cases you're not going to have to send back that item that you're removing and now it's simply about making this app better because yes we have the core functionality in place we can definitely test it out on the front end and everything is awesome but there's some things that we would want to fix for example i want to remove all these strike catch blocks i don't want to repeat myself in such a way i also want to set up one place where we're dealing with errors and other improvements so in the following videos we'll make our app better so we have the core functionality in place now we just want to make it better all right and up next i want to finally discuss put method versus patch method so why in this api in our routes we used patch and during tutorial we used put so here's the deal yes put and patch are both are both for updating the resource but the assumption is that when you use put you're trying to replace the existing resource and patch is for partial update and since i'm fully aware that this might sound like mumbo jumbo to you let me give you an example so if we go to our postman and then more specifically update task if the id is correct then only the properties that i'll pass in will be updated so in this case if i'm gonna go with shake and bake number two and i'll actually remove completed only the property that is passed in will be updated so if i send check it out now i get the task and i can clearly see that completed is there even though i didn't pass it why well because that's how our functionality is set up in the controller so if i'll pass completed and i'll set it equal to false of course it will be updated as well so if i go here completed and i'll set it to false yes in this case since i'm passing the property of course now i'm going to get the new result now what is the difference with put well let me go the long route and actually set up one more controller but keep in mind that this is going to be just temporary controller so if you don't want you can just sit back and relax and we'll start in our routes where essentially i want to go with my route and in this case i'm still looking for this forward slash and then colon id because again the functionality is going to be almost the same but i'm looking for a different method and i'm looking for put and of course now we just need to create the controller and in my case eventually i'll call this update or i'm sorry edit task just so it's a little bit different so of course i'm not exporting that yet but i'll right away set it here in my structure i'll say edit task and then back in the controllers i just want to go below the update task again this is just going to be temporary but i'll go with const edit and then task and that one is going to be equal to whatever i have over here we simply need to add one more option in the find one and update so let me select this whole thing just so we don't have to type it from scratch and all the way in the bottom we're going to go with edit task and like i said it's going to be temporary so in here i'm not going to save it with all my routes but let me just save my current ones and i'll close all of these windows and let's set up a new route so in this case it's going to be a put route and remember we have our variable so i'm looking for url and then i'm looking for the tasks and of course i want to grab some kind of id so let me get again all the tasks here and i'm going to stick with shaken back because i like that name so much so let me grab this id here then back in tasks i will pass it in and then let's try to recreate the same functionality that we have for now e in the patch and essentially what i really want is just to pass in some data in my body so i'm gonna go here with raw again we're looking for json and we'll set it up name equal to john nothing particularly original and once i save of course now shaken bake has the name of john but here comes the biggest difference between put method that we're using over here and the patch method so idea with put is that if i send only the name my expectation is that all the rest of the properties which of course in our case is just completed will be removed from that item so we will replace that item and how is that going to look like in our controller well here everything is going to be exactly the same but by default mongoose doesn't do that so by default mongoose is going to be like okay so you want to get the item you want to update it awesome just get me the properties you want to update and rest of them will stay the same and if i actually want to remove those properties the ones that i'm not passing in with my request i need to add another option here and the option name is overwrite and we need to set it equal to true so now you'll notice that back in my postman if i send here with name and let's just keep it interesting and pass in peter check it out we have name and the complete is still there now why it's still there well because in our model we have default set to false so there is some default one if i remove it you'll notice that with output method the way the controller works right now if i send it right now then of course i'll just get the name so completed is not there anymore so if i take a look at all the tasks now and the first one actually completed is missing so that is going to be the difference where when we work with put the expectation is that we'll replace the item so we'll just pass in the properties that we want to set up in item and then rest of them effectively will be removed but when we're working with patch we're just updating the properties that we're passing in just remember that in real life you will see the apis where the put method is used with the same functionality as the patch now in our case for the remainder of the project we'll use the patch one instead so therefore i'll remove this edit one and here as well and the same i want to do in routes like i said this is just for demonstration purposes so save it here and i also want to remove this route from my postman just so it's not in a way so say don't save and i'm back to my five routes and of course for the update i'm using the patch one and before we start refactoring our code and adding some extra middleware let's just spend a few minutes on our responses and more specifically on the other options you have when setting them up and i'll use get all tasks route as my example just keep in mind that the same goes for the rest of them and essentially when i was setting up the route i said that you have tons of options here as far as the response so in my case i'm just setting up course djson object and then i set the property tasks equal to tasks but you can also do something like this where i'll copy and paste and i'm going to go with res.status so this won't change we're just talking about the object that we're sending back and instead of simply just sending tasks you could also add the amount of tasks and for this property name of course sky is the limit whatever you want to come up with in my case i'm going to go with amount but you can also call it maybe value maybe the number of hits or something along those lines and here you're just looking for tasks and of course the length like so and also what we could do and i'll just comment these options out just so they can stay for your reference and let me copy and paste so i don't have to type arrest that status also what we could do well i could set up a flag here where i say success is equal to true and then of course we need to keep in mind if that is the case then you also need to add something here where you have the error whether that is 404 error or it's the general 501 so effectively here i just add this extra bit of data where i say yeah the success was true and then you can even place it in the data property and then say tasks is equal to tasks and also maybe add the amount so that's also something that you might see around for example the hacker news api uses the number of hits like so essentially you just get that value and again that is going to be equal to the array that you're getting back equal to a length and once i said of course my response is going to look like this now if you don't like the success one go maybe with status that's also something that you might see around where we set up status is equal to success for the successful responses and then for errors of course we're going to go with status and then fail or error or whatever string value you might want to set up and if you're wondering why am i showing you this is because i want you to be aware of your options so just because i'm setting it this way where i just pass in the tasks of course that's not a rule that's pretty much my preference and why i don't prefer setting up the statuses or successes or the data here that is simply because of the front end so in my experience when we use frontend there's two things that are going on effectively when we have asynchronous responses we already have try and catch and because of that i find the status or success to be a bit redundant because effectively just like i showed you with delete if i'm successful then of course this code will run regardless and then if there's some kind of error then of course i'm gonna have my code e in the cache block and why i don't like setting up the data well because on my front end usually i use axios and if you're familiar with axios it right away returns a data property so it right away has that data object so if you set this response in such a manner where you have data returned in the object then on the front end you'll have data and then in that data object you have another data so essentially on the front end you need to do something like this where there is a data object inside of that data object there's another data object and then you only get the tasks which is of course not the end of the world but in my case again i find it a bit redundant and lastly when it comes tutorials and courses i also enjoy the fact that there's less typing in the setup where i just pass in the tasks so be aware of your options my suggestion is whichever route you pick just stick throughout the api so there's no confusion don't set up one type of response for one route and then go totally different in a different route that's going to be very confusing to whomever is using your api and lastly let me just say this yes you can set up your own api responses however you like but if you want our front-end app the one that's sitting in the public to work properly the responses have to be exactly the same as mine because that's what the app is expecting if you'll set it up willy-nilly then you might get some bugs not bad not bad once we have discussed our response options next i want to work on route not found so at the moment life is awesome we have our application everything works if i go to index.html of course i can see the application if i go to api then version one and then tasks of course i can see all the tasks what happens if i go with api version one and then hollow so i have cannot get api blah blah blah and i can clearly see in my browser that of course we get 404 error but essentially this is going to be the default one and instead i want to set up the custom one just like they have in algolia one or again if you're looking for some kind of resource and the server can find the resource and essentially we still get the 404 but of course the value here is unknown now it doesn't really matter what you set up as far as the value just want to showcase how we can set up a custom 404 response and the way we do that we go back to our application here and then in the app.js i want to remove these comments because i think we're clear on the rest api and location here is very important so we have the middleware for public and json that still stays the same then we have all our routes for the tasks and then right after that we want to go with app.use and then we'll pass in our middleware function the one that will handle the 404 and send some kind of custom response now we haven't created it yet so let's go back to our starter we'll create a new folder because there's going to be a few middlewares that we'll set up in the upcoming videos so say middleware and then inside of the middleware we want to go with new file and i'll call this one not surprisingly not found and a js and as far as the logic well we'll still have access to erec and res so we just need to come up with function name in my case it's going to be not found and i'll set it equal to rec and res and then as far as the response i'm just going to go with res dot then status and of course in this case it's 404 so the server is letting the user know that it cannot find the resource and then as far as the message i'll just use the simple send and i'll say route does not and exist so now of course we just need to export this and we do that with module then exports of course and we'll set it equal to our not found and then back in the app.js above the app.users we're going to go with const not found is equal to require then we're looking of course e in our middleware so let me say dot middleware and then more specifically we're looking in and not found and then in the app.used we'll just stick not found one and once we save and in this case i'll just use the postman just so you can see that it's gonna work exactly the same and if we're looking for the url and then we'll go with hello now of course we have our custom one we have route does not exist which is pretty awesome and just to showcase that it's going to be the same scenario in the browser as well notice once we refresh we have route does not exist so we set up the middleware folder in there we have not found.js and then back in the app.js we import the function we set some kind of name in my case it's not found and then all the way in the bottom we go with app.use and we pass in the function and in that function we'll have access to rack and res and in our case we're just interested in response and we'll set up a 404 with whatever message we want to send back awesome and up next i want to work on asynchronous wrappers for all our controllers why well because we have asynchronous operations and yes it's very useful to use these try catch blocks but you'll have to agree with me that it becomes somewhat redundant pretty much for every controller setting up try and then catch and as you can see essentially i'm just copying pasting the code around so there has to be a better solution and that better solution is to create a middleware function that essentially we'll wrap our controllers and in there we'll just set up the functionality where we don't have to repeat ourselves and before we continue let me just say that there are some npm packages that do that for us and most likely in the upcoming project we'll use them instead since that way we can save some time on the setup but i think it's very important to have at least a general idea of what the package is doing instead of blindly installing it and therefore in our first project we'll set up the basic logic ourselves and we'll start over here with new file and i'll call this async js and then inside of it i'm just going to go with const async wrapper so i simply create a function at the moment nothing is happening here and then i want to export it so module exports and then a sync wrapper and once we set up the export now of course i just want to go to my controllers and import that middleware so i'm looking in the middleware and i'm looking for async so in here let's just call this a sync wrapper again and that is equal to require then we navigate to our middleware folder and of course we're looking for the async and now what we want to do is wrap all of our controllers now i'm not going to wrap all of them right away i'll just start with get all tasks just so you understand how it is going to work so what we want to do here is just to take this async wrapper this function and just wrap our current controller and essentially it's going to look like this where we go with a sync wrapper and we pass in the controller the current controller as an argument and since we know that we can do that in javascript we are in good shape so we pass it in and then back in the async of course i need to set up the parameter so since i'm passing in already in the controllers my function my controller as an argument back in my sync js my middleware i just need to go with some kind of parameter now you can call this callback you can call this function it doesn't really matter in my case i'm just going to go with fn and what am i trying to do here well i'm trying to avoid this try catch so essentially i want to have my cake and eat it too where i can still use this nice await syntax but i don't have to set up these try catch blocks how can we do that well we set up the try catch blocks inside of the wrapper and the first thing that i want to do from this function is to return another one so in here i'll say return async and then if you remember in the express by default we right away got request response as well as the next so that's what i'm trying to do over here since i wrapped my controller in my middleware and if you pay close attention we're actually invoking the async wrapper right away now of course i want to pass in those request response and next down to my function down to this controller correct because now of course i wrap my controller in my middleware and the way we do that we return another function since i'll use a weight inside of the function body that's why i set it up here as async and please please please keep something in mind where these ones the wreck res and next we'll have access to right away because at the end of the day we return another function from async wrapper and then inside of the function body one of the things that i want to do is pass these rec res and next from express down to this function so hopefully that is clear again we get these ones by default the reason why we have access to them because from our async wrapper we actually return another function so that's how we'll have right away access to them and then in the function body we'll decide what to do with our parameter with our argument which is our current controller and as far as logic i want to go with try catch block and then inside of the try block i'm going to go with a weight and function and here we'll pass in rec res and next and then once we have passed all of these things down to our controller of course now have access to them in here as well and there also since there might be a case for an error we'll go with next and then we'll pass in the error and if you're wondering what's happening over here essentially we're passing this to a next middleware which we haven't set up yet e in our app.js so that's what's coming up in the following videos we'll set up another set of middleware and in this case we'll deal with errors so once we save over here we can go back to the controllers and now i can remove the try catch block so remove the try catch block completely and at this point you should only have these two lines of code where we're waiting to find all the tasks and if we're successful we send back those tasks and as far as the async wrapper we take our controller as a argument and then since we return the function we have access to rec res and next that are coming from the express and we set up the try catch block and in here we have a weight because our controller is still async and we know that by default a sync function will always always return a promise so in here i just have a wait and i'm waiting for that promise to be settled either resolved or rejected and since my controller will still need to access rack res and possibly next since i get them from express i pass it down to my controller and then if there is an error so in here if we trigger some kind of error whether in get all tasks or any of the controllers then of course we'll catch it over here and we'll pass it to a next set of middleware which we haven't set up yet and now of course once we have everything in place now we just want to apply these changes to all the routes now i fully understand that some people are very negative about refactoring the code and to some degree i sympathize with that because i also hold the opinion where it's not very useful if we're all the time refactoring the application but it was important for me to show you the long way first because that way you have a good understanding of how everything works and now we just set up the middleware that actually handles that so let's go back to the controllers and slowly but surely let's add this a sync wrapper to all the routes and the setup is going to be following for all of them where we start with a sync wrapper so we set up our two parentheses here and we need to make sure that second parenthesis the closing one is right after the curly brace correct then we want to remove the try block as well as the catch block and again we'll be just left with wait does that create if we're successful we send back the task and effectively we want to do that for all our controllers so let me go here with a sync wrapper same deal wrap this guy here and then we have try and we remove the catch but we are leaving this one so i will work with this one a little bit later for time being we'll leave it as it is with this response and once we set up our custom error there's going to be some changes here as well let's keep on scrolling we're looking for the async wrapper and again we want to add the closing one right after the curly brace we still pass in the function i'll remove my try i'll remove my catch here and we'll save it and the same goes for updating a task as well so we go here with async wrapper and we'll close it then we want to remove try and we want to remove catch and just to try it out why don't we go to create task and then i'm just going to go with creating task creating task let's try it out everything still works i can create my task but if i'll try to add a task with an empty string value i should get the error and i do but of course this is not the error that we're sending so that's something that we're going to work on in the upcoming videos and once we have set up the async wrapper next i want to work on catching the errors and we're going to start our journey actually in the express documentation so go to expressjs.com and then in search box just type error and first let's take a look at the default one and if you take a look at the first sentence express comes with built-in error handler that takes care of any errors that might be encountered in the app this default error handling middleware function is added at the end of the middleware function stack and if we pass in error to the next and you do not handle it in a customer handler it will be handled by the built-in one why am i telling you this well because that answers this question where is this response coming from well that is coming from the default built-in error handler that's point number one i want to make otherwise you might be wondering well where are we getting this info second next correct that's why in the async wrapper we set up this next and error so we passed it to the next middleware but in our case of course we haven't set up that handler yet so therefore it was just eventually passed down to the built-in one and lastly if we go back and if we say here error so i'll search one more time and in this case we're looking for writing error handlers so this is what we're about to do we'll set up another set of middleware however in this case the middleware will handle errors and you can see that if we want to handle errors we just pass in four arguments and then the first one will be that error and then we want to place that at the very end of our routes so let's just navigate back and of course in the example they showcase how they right away set up the middleware in the app.js in our case since we'll have more code essentially i want to create another file in the middleware so in here i'm just looking for new file and i'll call this error and then handler and inside of the file i just need to come up with the function and i'm going to go the long route where i'll say error handler middleware and that is equal to error again in this case we need to have four parameters request response and we also have next and as far as the logic we'll add more code once we set up our own custom error class but for time being we just want to go with return and res that status and if you remember that's exactly what we had previously e in the try catch block and i'm just going to go to 500 and we'll say json error and error is equal to error now if you want you can cancel log it of course but the result is going to be exactly the same where in here we'll have access to that error the one that is going to be coming in our case from this async wrapper and then we just need to decide what we want to do and i'll just start by setting error equal to error and you're not actually i want to go with message is equal to error and now we simply want to go back to app.js where we have not found let's just copy and paste and now we just need to come up with a name and as you know naming is probably the hardest thing in programming so in my case i'm just going to call this error handler and then middleware and of course that one is coming from the file that we just set up the error handler and then we want to scroll all the way down and right after not found we're going to go with app.use and of course we'll pass in the error handler middleware and once we save and we go back to the postman and try to send the same request meaning the request with a incomplete data then we should get a different response but we don't effectively it looks like i have a bug so let me check the error handler and yes of course i didn't export the function so let me go with module exports and that one is equal to a error handler one and of course if i test it out right now i should see the custom response and we can clearly see that because we have the message now like i already mentioned previously if you don't like these big massive error messages you can simply go back over here and instead of setting the message equal to an error you can just hard code some kind of message so you can go something along the lines of something something went wrong comma try again later this is what we'll see in postman again we send and now of course our message is shorter so essentially this is how we can set up a custom error handler in express where we add another piece of middleware and then in there we have four arguments and the first one is going to be the error and of course in our case the way we pass the errors down to this custom error handler is by using the hsync wrapper and there we have the next so as you remember from tutorial with next we pass it to the next middleware and previously we used the built in default one and now of course we have our own where effectively you can set up whatever logic you want if you want to send this as 200 nothing stops you from doing that but of course a more meaningful response would be with some kind of error code and with some kind of meaningful message whether that is hard-coded string or you can pass in the entire error object and right after we set up our custom error handler let's work on our 404 responses too and essentially i want to set up a custom error class which extends from the general javascript error class and that way we can handle all of our 404 responses in our newly created error handler as well and we're going to start by navigating back to the controllers and the routes or controllers that i'm looking for are following i want to work on update task here we send the 404 then the same is for deleting the task and of course getting the task and let's just start over here with getting the task and simply i want to showcase that we can create a new error object if we run the built in javascript error constructor and we go here with const and no surprise i'm going to call this error and that is equal to new and then we just go with error and here we pass in the message so i can say not found and then next line i'm just going to go with error so now i'm dealing with the object that i just created and i'll set another property on it and i'll say status so that's the name of the property and of course the value will be 404 so now if you want you can console log it here or what we can simply do is use next and pass this guy down to our custom error handler remember that's how it works we call next and then we pass in the error and of course in this case we are creating that error ourselves instead of getting it from the mongoose and the only thing that's missing right now is in our controller because we don't have the next so i want to go here with next and then we need to go with return again i already mentioned why we want to do that because we don't want javascript to keep reading the code now of course we have this one right now but hopefully you get to just where we need to go with return and then next and now of course i want to pass in my newly created error object and once i do that if we go back over here in the error handler and if we simply cancel log we should see our newly created error object so i'm going to go here with console.log and i'll look for my error and now let me go back to the postman and essentially what i want to do i want to get all the tasks and then i'll look for one of the ideas but again i don't want to get that cast error so i still want to keep the same structure i just want to pass in the wrong value so i'll look for single task i'll copy and paste and then instead of three i'm gonna go with four so once we send of course we get our custom error message as vague as it currently is and then of course in console i can clearly see that i have not found so of course that is going to be my message and i understand that it might be a bit confusing but effectively the idea is following where once we create this new our object that property is going to be on there so in order to access the string value we'll have to go over here and simply go with error and then that message and as far as the status well we can clearly see it here we're going to have 404 so now just for kicks what we can do is set up message is equal to error message like i said there's the property on that object and then as far as the status well i can simply change this one around where instead of 500 i'll pass in error and then status and don't worry of course there's more code coming and once i have applied these changes of course we can swing back to our postman and check it out now of course we have 404 and then the message is not found so that's pretty cool now of course we just need to go back to the tasks and set it up in such a way where we don't have to do this all the time manually and the idea is following where again we'll create a new class a new custom error class and we'll extend it from the javascript error and then we'll create a new instance and yada yada and effectively the way we want to do that we want to create a new folder and i'll call this errors pretty self-explanatory so we're going to go here with new folders and we're going to go with errors and inside of it i'm going to create another new file and in this case i'm going to call this custom and hyphen error and of course i'm going to add the js extension and then instead of my custom error now i want to extend from the error class now here's the deal in this case i'll just write out the code and then i'll go line by line of what's happening because i think that's going to be a bit more productive so let's go here with class and then we just need to come up with a name in my case i'm going to go with the long one i'm going to say custom api and then error now we need to use the extends keyword and since i want to extend from the error class i'm going to go here with error and as far as the functionality we want to go with constructor and here we'll pass in message and status code and then inside the constructor we want to call super then pass in the message and right after i call super i'm going to go with this dot status code and i'll set that one equal to whatever i'm passing in the constructor so in here i'll pass e in the status code and as far as these few lines of code a constructor method is a special method we invoke when we create a new instance of a class and in our case we'll pass in two arguments an error message and a status code then since we're extending basically we're setting up a child class we need to call supermethod which in turn invokes a constructor of a parent class and in our case we pass in our message value as a result we'll have access to all the methods and properties of the parent so in our instance we'll have the message property and with this dot status code we create a status code property as well and that's how we can create our new custom error class and essentially if you want to create new instances you can simply go with custom and then api error and then pass in those two values the message and status code but i actually like to set up a new function that does that for me and here i'm going to go with const create custom and error and this function is going to be looking for two parameters a message and then a status code and what i'm going to do is from this function i'm going to return that new instance so i'm going to go to return new and then we're looking for custom api error and then of course we'll pass in the message here as well as the status code now of course if you want to keep the same parameter names you can definitely do so but in my case i'm purposely setting this up so you can see that this is coming from the function as far as the message and of course i pass e into my custom api error more specifically in the constructor as a message and then of course we just need to export this and we'll have to export both of them and you'll see in a second why so we're going to go with module exports is equal to an object and then we're looking for create custom error and then custom api error and once we have both once we have the class as well as the function and we're exporting both now of course we want to go to the tasks we just need to remember that of course we're exporting object so therefore we'll have to provide a specific name in our case i'm looking here for the function so i'm going to go with const i'll set up my curlies and i'll say create and then custom and error so of course that is my function set it equal to require i do need to go two levels up so in here we're looking for the errors and then more specifically i'm looking for the custom one and then i want to replace all of these three instances and of course i want to remove this manual code as well so start over here and then i'll keep this one for the second just because i want to reuse the same message and the idea is following where we go with return then next and then instead of the next we pass in create custom error and of course we want to pass in the message so that's why i'll just copy this one just because i want to speed this up and then the second thing is going to be my status code which of course is going to be 404 and now we can remove the second line and we just want to copy and paste so it's the same deal over here and the same in the update task as well and once we have all of this in place now we just want to go to error handler so our custom error handler and instead of looking for the function we're looking for the class because in here i want to check if the instance is equal to our customary one then of course i'll pass in the status code and the error message however if there is any other error then of course we'll just go with res.status 500 and whatever we had before so let me go at the top and i'm going to go with const again it is named import so we're looking for custom api and then error and that is equal to require and same deal we go two levels up we're looking for errors and more specific custom error and let's right away set up the default one and this one i'll set it back to 500 here and then as far as the json let's go with the same message i'm just going to say something went wrong please try again and above this return we're going to go with if and then we'll check if the error is the instance of our custom api error then of course i want to go with return and i want to pass in the res dot status and then that will be equal to a error dot status code because of course that's where the value is sitting in that property and then when it comes to the actual message same deal i'm going to go with message and this will be equal to error and then we're looking for the message property and once we save let's go and test it out or essentially if i send it here from the postman of course i'll have no task with this id and if i'm going to mess with the syntax i should get the cast error which of course i do because i can clearly see that something went wrong please try again lastly let me just repeat one more time that error handling and validation is something we're going to return to later most likely in a separate project this is just a general setup just to get you comfortable with overall ideas and later we'll work on more complex validation and error handling approach nice i think we're done with error handling at least for now and now let's talk about deployment and right off the bat i want to say that we're not going to deploy this project simply because we have not covered authentication yet as well as extra packages for security and deploying the project where anyone can tinker with all the data is somewhat irresponsible and it actually can lead to a lot of headaches but with that said there is something deployment related i want to cover and that is our port variable you see hard-coded value like port 3000 or 6000 or 7000 is decent solution in our local environment but when it comes to deployment in many environments the host so the platform where the project is hosted on may want to independently set the port value to whatever makes sense to the platform because as you can imagine it needs to handle more than just one application at the time and in order to make that possible when it comes to port value instead of hard coding to 3000 6000 or whatever we'll have to use the port variable that is available in process.env instead and setup or operator just in case it's undefined and in order to set that up we need to go to our port variable that's why in this case we set it up as a variable and then before d3000 we actually want to go with process and then dot env and then we're looking for the port variable so we go here with port and then if it is set then of course we'll use that value if not then we'll use the or operator and then of course we're going to go with 3000 now of course in a local environment by default it's not going to be set so always go back to the 3000 however once we deploy it's going to be a different scenario now if you want to test it out in local environment you can actually do so and we do that by stopping the server and then we want to go with a port and we set it equal to whatever value you want now my case i'm going to go with 5000 because i believe my final one is using that so i'm going to go with 6000 and then you want to go with node and then what is the name of the file you want to run of course it is app.js and now check it out in a console we should see six thousand now of course i still see three thousand because i didn't save the file my apologies let me stop the server just so you don't think that i'm messing with you and let me run the command one more time and now of course in the console i can see server is listening on port 6000 and one more time as far as our logic we just say set port to whatever is the environment variable by the name of port or 3000 if there's nothing there awesome congrats on completing the project and i'll see you next one all right and welcome to our next project the store api where we'll learn the advanced filtering sorting and dynamically populating our database as well as bunch of other cool stuff while i did not create the front end for this project just because it seemed like an overkill the idea is following imagine we're in charge of store api and we want to provide a bunch of search options for our users everything starting with search by name to filtering based on price amount since we'll cover all the options in great detail during the project i won't do it right now but i do want to showcase where i got the idea from and how that would look like in real life and it's probably not going to be surprised if i tell you that i got this idea from the hacker news api and if you remember they offer quite a few search options for their user now we're not going to implement all of them but we will mimic the major ones and as far as how it's going to look like in real life if you took my react course you probably worked on a store project and during that project we built the entire search functionality on a front-end now imagine once we're done building our api the front-end only needs to make http calls and we send back the data so the same result user can still search for products but only this time the backend does all the heavy lifting and frontend is only responsible for http calls so the user can still search for products whether that's based on name or category or company and of course you can read the rest but the difference is of course that now the front end only makes the http call and then the back end does all the heavy lifting and as far as the project setup again we've got two folders final one and starter one and of course the final one is for your reference and the starter one is where we'll do all of our work and just like in the previous project when it comes to final in order to run it you'll need to complete some extra steps first not just npm install and of course i'll cover all that during the project as far as the starter most of the things should look very familiar since we covered them in the tutorial as well as the previous project and you'll also notice that in order to save some time on a boilerplate i already prepared a folder structure for you now when it comes to files most of them are empty since that's going to be our job during the project but the folders are already there while i understand that some people like creating everything from scratch since we're going to be building quite a few projects in my opinion there's very little benefit to repeat all the steps every single time all right and once we're familiar with the setup now let's kick things into gear and of course let's start working on a project and the first thing we need to do is install all dependencies and we do that by navigating to the starter so again big picture we're looking for fourth project so zero for store api and then more specifically the starter and i think the fastest way is just typing cd and then take the folder drag and drop and of course we're sitting in the folder and then we run npm install and while the project dependencies are being installed let me just mention that in this project we will set up everything from the scratch just like we did in the previous project just so we can keep on practicing on getting our project off the ground but starting with the next project some of the boilerplate code the one that we'll type in this and few of the following videos will be already prepared for you since that way we can right away cut to the chase and don't waste our time on stuff we already covered and once the dependencies are there then of course i just need to check the package.json and i can clearly see that the command is npm start and of course we just spin up the nodemon so we go here with npm start and we are in good place now of course let me navigate to the app.js and here let's start adding the code and the first thing that i want to do is get that package in the env so i have access to environment variables because of course again we'll connect to our database and we simply do that by typing require then we're looking for dot env that's package name and if you remember we invoke config now of course we haven't set up the env yet the file e in the root of our project but we definitely need to use the dot env if we want to access the variables and of course we'll work on that envy once we actually start connecting to the database then i'll add a comment of async errors and you'll see why i do that in a few videos and then of course we want to spin up the express so we go here with const and express is equal to express of course so i go here with require and then express and then once i have the package then of course we want to spin up the app so we go const app is equal to express and then of course we invoke it now i'll start listening for the server a little later now i just want to import two middleware functions that we set up e in the previous project and those are error handler so this one over here more essentially we just catch all the errors and then we decide what is going to be our response and then the second one is not found because this is going to be the case where i don't want to repeat the same stuff we already covered in the previous project so that's the code that i already prepared for you and now we simply need to import both of them and come up with some meaningful names in this case i'm going to go with not found and then middleware and that is equal to require and of course i'm looking in the middle or folder and then more specifically we're looking for that not found one then we'll copy and paste and then just change the name where instead of not found we're gonna go with error and of course the file that we're looking for is also different and i called it error handler and once we have both of these imports in place now of course we can set up the express json middleware as well while we're at it and you know what in here let me just add middleware comment and then like i said we're going to go with app.use and then we'll pass in the express and we're invoking json then we'll set up our one lonely route for time being and essentially this is just for testing so let me add here routes eventually of course we'll set up the router and all that but for time being we're just gonna go with app.get we're going to be looking for the home page meaning the forward slash and then we'll set up rec and res so of course our callback function and here let's say rec and res and as far as the response i'm actually going to be cheating a little bit where i'm going to go with res.send and then since i can pass in some html i'll say heading 1 and name of the project store api and of course now i want to close my heading 1 and then also i want to set up a link that will navigate to the products page the one that we haven't set up yet and here let's just go with ahref and i guess more correctly the product route because technically we'll be sending json it's not going to be a page and here we go with forward slash api and then version one products and i'm purposely keeping this api in version one just because we already have the global variable in a postman and then as far as the text let me just close it here and then close the actual tags and then we'll say product route so that way if we ever need to we can just quickly navigate from the browser as well so let's save this one and let's keep it going and in here i'll add a comment for product route that we'll set up in the upcoming videos and then i want to use both of these middlewares so we have not found an error middleware and i simply want to use app.use but make sure you do that right after the app.get so we'll say here app.use and first let's just look for not found one and then we'll do the same thing with the other one as well so pass here error middleware then i want to set up my start function but initially i'm not going to use that connectdb so simply just go with app.listen but we'll place it in a start because of course eventually we will connect to the database so let's just start over here start and it's going to be async and then as far as the function body let's just go try catch and then eventually we'll connect to db connect db but for time being we just simply want to go with app.listen and then what is the port well we need to create that port variable and if you remember the end of the previous project effectively we'll set this up dynamic where we'll go with const port is equal to process dot env online port if it is undefined then of course we can hard code this value and i believe that in my final one i have 5000 so i'll keep this one as 3 000. and then we'll pass in that variable here the port one and then of course let's set up the console.log just so we can see that everything works and here we'll just say server is listening to the port and then whatever is the port variable so let's say you're here port and then i'll add those three dots and then if there's an error of course we'll go with console.log and the error and now finally we can just invoke start and if you can see in a console server is listening on port 3000 then of course we are in good shape and if you want to test it out in the browser just navigate there look for localhost 3000 and of course this is what you should see the hearing one as well as link now we don't have the route for api version one product but we can nicely test r404 since we can see the route does not exist text and if we have all this in place now of course we can move on to our next topic and once our basic express server is up and running next i want to connect to our database and if you remember we just need to navigate to the atlas and then we're looking for connect so that is going to give us that connection string and of course we'll have to supply here the proper values so let me just grab this one then we're going to navigate back to our project and of course i'll right away set it up in dot env so in the starter make sure it's in root we're going to go with new file and then we go dot env here and then once we have the file then of course we want to create a new variable and since it is a common practice to call this uri we'll do the same where we'll say underscore uri is equal and now of course we copy and paste now as far as the database i'm gonna call my one zero four and then store api essentially the same as the project name but sky's the limit you can choose a different name of course as well and then as far as the password since i changed from my silly one two three four now of course i'll freeze the video so you don't see what is my real password and then once you add your own password then make sure that you save dot env that's a must then we want to restart the server so in my case i'll stop the server with control c and then again we go with npm start and then once everything is in place now of course we just need to go back to app.js and i just want to showcase that of course the function is already there so the only thing you'll need to do is just to invoke it in appdress of course you need to require it and then pass in the connection string with proper values and since we already covered all of this setup in the previous project essentially there's really nothing new that we can learn over here i already prepared all the code so we simply need to grab this function and then pass in the correct connection string so let's go back to app.js and i guess we'll do that somewhere at top so right after app and before the middleware we're just going to go with const and again i'll name it exactly the same connect db and that one is equal to require we're looking in the database folder and then more specifically we're looking for connect now this function of course returns a promise that's why we set up start with our sync and then right above the app.listen i'm just going to go with await connect db and then of course i'm looking for my variable the one that's coming from the dot env and i simply go here with process and then dot env and then of course the variable name was uri and if you see in a console server is listening on port 3000 then of course we are in good shape and we can move on to our next task and once we have successfully connected to the database next i want to set up two routes for the product and you'll see why we have two routes essentially the idea is that one of them the first one is just going to be for manual testing and then since i want to keep on practicing on setting up the router we'll do just that and up here i can notice that i actually have a spelling bug or this should be route and then right after the home route i'll set up my router and i'll do that using add.use and then i just need to come up with that base path or root path for the router and in my case like i already mentioned i'm gonna go with api version one and this is gonna be looking for the product and like i mentioned when we're setting up this route i simply add this api in version one because that way it's easier in postman since we already have that global variable and effectively in here we want to pass in the router but in order for the router to work of course we'll have to set up the controllers as well therefore we'll start in the controllers the file is already created for you and the name is product and for time being we'll simply set up two functions and we'll just send some dummy data back and two functions are going to be following we're going to go with const get all products and the first one i'll call static now this is going to be async since of course we will use the methods that we have on the mongos and here let's look for rec and res of course and then as far as the function body for time being simply want to go with res dot status and i'll set it equal to 200 and then as far as the response i'm going to go json and then instead of the json i'll pass in the object and in here there's going to be a message property and then we'll just write products testing route now let me copy and paste this and then we just want to remove that static part and we also want to remove the testing one so this is going to be actual route and then of course we can export this so let's go with module exports and this is going to be my object and here i simply want to pass in both functions so get all products and get all products static so we set this up then of course we need to navigate to our routes so in here this is where we'll set up our router and then we'll start by getting the express so const express is equal to require and then we want to pass in the express of course again and then once we have that let's set up the router and if you remember the syntax is following where we go with router and then we go with express dot and then with the capital case we go with the router and then of course we invoke it then i want to import both of these functions from my controllers and i'll right away use the structuring so go with const and then the name is get all product of course and then get all product and we'll add a static one and that is equal to require then we're looking in controllers and then of course the file we're looking for is the product and then if you remember we have multiple options and in this case i'm going to go router route and then i'll go with forward slash so essentially this is going to be for that main route here the api version one and product and as far as which controller i want to use i'll use this get all products and please don't mix them up again the controller you want to pass in is get all product and as far as the static one let's copy and paste and then we'll just add that here at the end so this is going to be our main path or root path and then we're going to go with forward slash static and this is where we want to pass in that get all product static and then once we have this setup in place now of course we just need to export this so look for module exports and of course we'll export our router and once we have set up the routes then of course let's just finally navigate back to the app.js of course we do want to import that and come up with some kind of name and in my case i'm going to do that right after the connectdb and we'll just say const and i'll name this product router and that is equal to require and then i'm looking in the routes folder and then more specifically you want to get the product and then let's keep on scrolling and where we have app.use for our middleware now of course we'll pass in our router so let's just say here products and router and once we save i'll spin up the server one more time and if you want to test this out let's just navigate back to the browser so i think you can close this one and then at the moment it says route does not exist but once we refresh check it out of course now we have message product route beautiful and then if we want to test out the static one well we have product testing route and once we have all of this in place now of course we can move on to our next task and since we have both of our routes in place i think it's an awesome time to actually set up a new collection e in a postman and of course set up those routes as well so in here i'm just gonna save pretty much everything from the previous project close all the tabs here i'll say yep save changes and what i'm looking for of course is the new collection so i'll say here new collection then i'll right away rename it and i guess i went for edit should i went for rename and then we're gonna go with or at least i'm gonna go with zero four and then store and then api and then in here we'll set up two routes basically one for the product the api version one and then product and the second one for the static one so at this point i think i can close these tabs here and we're looking for new request now both of them are gonna be get requests so let's go over here url and then we want to go with double curlies and then we're looking for the products let's send and check it out of course we have product route beautiful again save as or you can simply click on command s and this is going to be get all products okay awesome we're looking for store api let's save it over here and now let's just add that static one as well and i'll do that by opening up a new tab again same thing get route and then we're looking for the url one and then once we have the url uh the products and then of course the static one as well so static here let's send because now we have product testing route and as far as the name i'll just call it that i'll say get all products but i'll say testing and once we have both routes in place now of course we can move on to our next topic and once the postman is ready to go and before we deep dive into the mongoose now let me showcase something in our application where if you take a look at the middleware you'll notice that there is no async wrapper and if you remember we needed to use something either we set up try catch pretty much in every route correct or of course the other option was using that async wrapper but when we were setting it up i also mentioned that there are packages that do that for us and that's why if you take a look at the package json you'll notice package the express async errors and essentially the only thing we need to do is just go back to app.js and then where we have a comment for async errors just import the package that's it that's all you have to do so let's go over here acquire and then of course we're looking for the package name of express async errors and just to stay on the safe side i'll stop the server and i'll spin it up one more time and now you'll notice that if i go back to the product one and or i'm sorry the products in the controller i'm actually going to close the routes i don't think we'll need that anymore as well as the app.js we're pretty much done over here and then if in any of the controllers you'll go here and throw the error which you'll notice that will actually be able to access that error in our custom error handler and essentially what that means is that whenever mongoose is going to spit back that error unlike the previous time where initially we set up trying catch and then we built our own async wrapper in this case the package takes care of that so in here let me just go throw and i'll call this new error and i'll say testing package or testing async errors whatever you want testing async errors and just to showcase that in the error handler i have the console log for the error and of course in here i'm sending back some kind of hard-coded message so first what i want to do is from the postman navigate to my static one just to showcase that of course we are catching those errors nicely with our package and then i'll cover the package in more detail so let me go back to the postman unfortunately it's all the way on the left-hand side so there's a little bit of jumping here and i'm looking for the static one i simply wanna invoke the route and now check it out something went wrong please try again and if i navigate back all the way here in the bottom i should see error testing async errors and if you're interested in finding out more about the package just go to google and type express async errors and of course one of the links is going to lead back to their docs and effectively if you want to use it in your own project just go with npm install express async errors then we keep on scrolling and notice how the only thing we need to do is to require it and then we're good to go now one thing you probably noticed that i did not use next and essentially the reason why i didn't do that is because if you read their docs they say that instead of using next we simply need to throw a error and of course since i can see the error in the console that means that i am getting that error in my custom error handler so the functionality still works so long story short instead of setting up try catch instead of setting up our own middleware we effectively just used a package that does all the work for us and as a result we can eat and have our cake too meaning we get the benefits of just using asynchronous code and we don't need to worry about setting up try catches or our own middleware and the package name that does that for us is a sync express errors and we simply need to require it in the app.js and once we have discussed async errors next let's set up the model and before we go anywhere let me just mention that i will keep this console log just because i want to showcase some stuff here and there but of course if you don't want it you can just remove it or you can maybe pass in the error over here where you have the message like we did in a previous project that is totally up to you now let me just navigate to complete project and you know what i'll make this one all the way on the left and what i want to showcase is that of course we have the products and what do the products have well they have some kind of properties correct now featured rating created that and of course you can read the rest and in order to set it up what are we going to need we will need a schema correct and using schema we'll set up a nice structure for our data and we already know how to do that so of course we just need to create a model and therefore we'll right away have a models folder and in there we just have the empty product js and in here we need to start by getting the mongoose and of course i'm looking for my mongoose package so we go here with the require and we're looking for the mongoose then we want to go with our schema and i'm going to call this product schema so that's going to be the structure for my product and i'll set it equal to new mongoose and then of course i'm looking for to schema and then in here we want to pass in the object and this is where we'll set up the properties so this is going to be a good refresher on how we can set up the properties as well as the validations and the properties i want to set up are following i want to first go with name and now we'll have a type of string then we want to go with required and remember we had multiple options and one of them was setting this up as an array and the first values of course is going to be true or false and then the second one will be that custom error message and here we go with product name must must be provided and then in order to save a little bit of time i'll just grab this whole thing copy and paste at least once and then the second property i want to set up is the price and of course this will be a number so let's go over here say number and then as far as the error message let's just say product price must be provided after that we want to set up a feature property and we simply do that by going with featured that's the name of the property again we'll set it up as an object and then type is going to be equal to our boolean and then by default we'll just say that all the products are not featured so that way of course we don't need to worry about whether the product is featured not we simply set all of them as false then we want to go with rating now of course if you do provide featured as true then of course it will be featured but by default all of them will be false hopefully that is clear then we want to go with rating and now we'll be equal to a number so we're going to go here with type number and let's just say that as far as default value it's going to be 4.5 again if the number is provided of course that value will be set up as far as the rating but if there is no number then there is a default value and then we want to go with created at so essentially this is just going to be a date when this product was created and what's really cool that in mongoose we can use date type and we can actually set the current time and we do that by creating the property created at we set it as an object and then instead of the object let's go with type and then date and then if we want to set up the current time we simply go with default and then we go with date dot and then we invoke now so now of course every time we'll create that new product if we don't supply the created ad by default is just going to be a current time and then we have company and company is a little bit interesting where essentially if you take a look of course we have the name for the company but when you're adding the products what we want to do is set up some kind of guardrails where we can only provide specific companies and if you're interested how that would look like in a real project so imagine the scenario you have the product and then as far as the companies these are your possible values that's it it's not like i'm just gonna randomly add here trader joe's or lucky donuts or something along those lines and the way we can set that up in mongoose is following where we need to go with company here and of course i'll set it up as an object then as far as the type yes it's going to be a string but if i want to limit the possible options for this property then we go with enum property and then in this array we provide those options and in here of course you can provide whatever values you want now i strongly suggest adding the same values as me because in the next video we'll dynamically populate our database and if your values will differ then of course you might get the bugs and companies that i chose are following so i went with ikea or in some places in the world they're also called ikea which is very very weird and then let me check the other ones so i have this one then let's keep scrolling i have this one and you know what in order to avoid confusion i'm just gonna avoid actually pronouncing them then we have this one and then let's add a comma again copy and paste and of course in here i added those double quotation marks which is probably not something i want and then i have the last one let's keep on scrolling this one over here so those are the four values that i chose and again for your own project you can set it up however you would like but since we'll be adding those products dynamically in the next video so we don't need to add them one by one i strongly suggest using the same values now what's also really really cool is the fact that we can set up a custom error message if the value doesn't match any of these items in the list and the way we do that is actually following where i'll comment this out just so it stays for your reference and we actually set it up as an object here and then as far as the possible values we go with values property and of course we still use the same values and when it comes to custom error message we go with message and then in order to access the value that the user is providing meaning the one that is coming in with a request the syntax is following where we go with curlies and then value so essentially that will access whatever the user is providing and then we want to go with some kind of message and in my case i'm just going to say is not supported and once we save we have our schema ready to go so now of course we just want to set up our model so we're going to go here module export and we'll set it equal to mongos model and then as far as the name i'm going to go with product and then i want to pass in my schema which of course is the product schema so product schema over here and once we save we're ready to move on to our next task and once we have our schema and model in place before we can start setting up any kind of functionality of course we need to have data otherwise how you're going to set up any kind of filtering if you have no product in a database and effectively we have two choices you either can set up a post route and then just manually add them or a better approach is just to automate this and essentially just have some kind of list and pass it on to your database now lucky for you if you take a look at our project you'll notice the product json and essentially this is just a list of products just so we can start working on the filter functionality and the only thing we need to do is set up populate js where we'll dynamically add all of these values to our database so instead of going to manual route we're one by one we add them we'll right away just add them to our database by actually invoking the populate.js and the way it's going to look like we're going to go over here we'll first grab our dot env so let's say over here dot env then we want to go with config and then what's really interesting that we need to have another connection so yes we have one for app.js of course that still stays the same but since we want to connect to the database one more time we'll have to grab that connect function as well and here i'm just going to go const connect db because that is coming from where that is coming from our db folder correct so we go here with db and then more specifically connect that's the first thing we want to grab then we want to grab the model and you'll see why and we just need to come up with the name in my case i'm going to go with product and then of course we're requiring that it is coming from the models and then more specifically product and then lastly i want those json products because that's the data that i'm going to be passing on to the database so here we need to come up with the name in this case i think i'm going to go json product and we'll set it equal to require and where the file is actually sitting right next to us so just go with forward slash and then we're looking for product json and once we have all of this in place we want to set up that start function one more time however in this case of course we're not going to be setting up app.listen we simply want to connect to the database and then use the model to automatically add those json products the one that we have in the file to our database and the way it's going to look like we're going to go here with const and start and we'll set it equal to a sync and in here we'll set up another try catch like so so let's go try catch and of course eventually we'll invoke it here as well and then i want to go with my await then we want to pass in the connectdb and of course inside of the connectdb we'll pass in the process dot env and of course our variable so and then underscore uri and just because i want to see whether we're going to get some weird bugs i'm also going to type in the catch a log so go over here with log and then we're going to be looking for the error and once we have all this in place we can at least try the connection now there's still some code that's missing but we'll get to it in no time so first what i want to do is stop the server over here and then we just want to go with the start invoke it and then in this case i'm not looking for nodemon i'll simply go with node and then of course i'm looking for the filename so since i'm already in a starter i just need to write populate and then once we run it if our connection again is successful we shouldn't see any errors in the console now if you want to help yourself out of course you can just type here log and let's just say success or something along those lines so let's say here success and an exclamation point let's save it one more time again let's stop it and if you remember from tutorial in order to go back to the last command we simply press arrow key up or down in micros i'm going to press it down and check it out now of course we have the success so we successfully connected to the database now if i want to check out the error i'll comment out the dot env stop the server one more time sorry about the detour but these things are important and then once we run it of course we're not successful connecting to the database because the uri parameter is not provided awesome so let me uncomment the env then clear everything and once we have successfully connected to our database there's two things that i want to do first i want to remove all the products that are currently there and then i want to use the create and just pass e and the json product so if you remember in a previous setup and i think i'm just going to go for final and let me look for controllers and tasks notice here this create we passed here a object correct when we were creating that task now what we can also do is pass in the array so if you take a look at the product and i'm sorry not this one products json you'll notice that this is an array at the end of the day and then since this is an array what i can do i can just pass this in into the dot create and then by doing so of course i'll add all of these products to our database so let's try it out let me navigate to the populate one i have the json product i'm in good shape so now let me go below the await but before the success and in here i want to go with await now i'm not waiting for the actual response and i want to go with my model because model has all those functions and then we want to go with delete many so now i just want to remove all the products that are currently there of course in our case there are no products but i'm just making sure that later if you want to reuse it then whatever gibberish you added or whatever data you currently have you just remove it and then you start from scratch this is technically optional if you don't want to do it you don't have to but in my case i always like to start with scratch and then we want to go with a weight and then product product and then remember the function create so now we're just dynamically creating a bunch of product by passing in json products that's all we have to do here we go with json product and now let's try it one more time and then of course we'll double check in our application so in here i'm going to go back to my console and then i want to go with node and populate and if i'll see the success then i know that i'm heading in the right direction so now let me just go back to my atlas one let me refresh and now where i have my collections i should have more values and effectively i have the store api awesome and in here i have of course all the products now i'm not sure how many i set up it really doesn't matter if you see these products added to your database now of course we can start finally setting up our filter functionality and while we're still on topic actually no there is a method by the name of exit now why that would be useful in our case because well let's think about it so we have our popular js if we're successful then we might as well just terminate the whole process correct i mean we don't need this file to be running and if there's an error then again we'll exit but maybe with a error code and the way we set up the process.exit is simply by navigating to the start here and then probably right after the success we'll set up a process again that is that global variable that we have access to then we go with exit and that's the method name and then if we pass in zero that just means that everything went well and we're just exiting the process however if i take the exit method and pass it in and of course in this case since i'm running it in the catch i want to pass in error code i'll pass in one and then let's do it one more time i'll clear everything and i'll not test it out with an error but let's just go here with node populate and now you'll notice that once we're successful we actually exit the process why well because we have process dot exit and of course the code in this case that we passed in is zero and if you want to double check your data just navigate back to the atlas and you'll see that all your product data is still there and once we have dynamically added products to our database i think i can just close the popular js at least in my case i'm not going to use it anymore the same goes for product js and then the rest of the work will pretty much do over here in the controllers and the first thing that i want to showcase actually this is a refresher where essentially if we want to search for a product in a mongoose meaning for some kind of items in our case of course that is product well we need to go with find method correct so let's just go over here i'm in the mongoose docs and i'm looking for the queries and then we'll keep on scrolling keep on scrolling in this case they show the find one example but the idea effectively is the same that if you go with find and of course if you pass in the mp object then you'll get all the documents and of course in the object you can also pass in some options and if you go with properties then you just need to provide what value you are looking for so in our case if we take a look at our model over here in the product js well these are all our properties correct whether that's name price featured and yada yada so in here let me start up my server and then back in product.js i want to get the model because of course we'll go over the basics first where i'll start by just getting the product and that is equal to require and i'm looking for my model again so i'll go two levels up and then i'm looking for the models and then the product and then let's start in the static one so i'll do a little bit of work here i'll show you the manual approach and then in get all products well this is where we'll set up the real functionality the one that we'll use in our project and then we already know the asynchronous so that's good and now let's just start by saying const product and simply let's take a look if we pass in the empty object so in here let's go with weight and then product that's the name of the model and then find and like i said let's just pass in the empty object and then instead of the message i'm just going to go here with product and then let's test it out in a postman so i'll go back to my testing one i'll send it and i should see my array of products and if that is the case then of course we're heading in the right direction now if i want to be more specific if i want to say hey get me the product where the company is equal to this one or get me the product where the name is equal to this one or maybe get me only the featured one then of course we simply need to go back here and where we have the object well i can say featured featured and then this is going to be equal to what true or false so let's just pass intro and then let's run it one more time and what you'll notice in your static route only the products that are featured are going to be displayed and you know what i think in this case it is going to be very helpful if i'm just going to go with those number of hits and i'll set it equal to my array because that way you can right away see if you're getting the correct set of data so let's go over here and in this case it says something went wrong and of course because for some reason i decided to add number of hits in the find and this is actually something that i'll cover later why we get those errors and how to avoid them so let me remove it this was pretty much an early taste what kind of errors we're going to have so let me run it over here where i have the json response so don't be like me be better than me and don't pass it into the find pass it actually where you are sending the response and let's go back over here let's send and of course i have the products and all the way at the bottom i have number of hits is equal to seven and if you'll take a look you'll see that all the products have featured set true and you can probably already imagine that if i'm just going to go here with name and of course we can combine them and again this is something that we'll cover in more detail in next videos so therefore i'll remove it and i'll just start with scratch i'll say name is equal to whatever i have here my apologies i copied the wrong thing if i have multiple tables and for some reason i just want to look for this one i can just pass e in the value where i say yeah get me the product but the name property needs to have this value and now of course once we send i should get only one that's the only one that has the matching name hopefully we're clear on a basic setup so now of course we can start implementing the get all products where the setup is going to be more complex than just hard coding the name or any of the other property values all right i think we're solid on filter functionality so now let's splice things up and implement the dynamic approach since it's highly unlikely that we'll send our responses based on hard-coded filter values and first let's start with our requests more specifically query params because that's how we will get our data and in order to jog your memory on query string params let's go back to my favorite api at least for this course of course the api is hacker news by algolia api and once we navigate here once we start scrolling and everything and looks like i'll have to refresh you can see that of course we can get the items we can provide the route params that's clear but if we keep on scrolling notice of course now we can start searching for some data and how do they set up the search well they have the domain then of course they have some kind of endpoint that ends with search and then they have a question mark and after the question mark we have key value pairs which essentially are query string parameters and then of course based on what you're looking for whether you intercept the query or you want to look for different page then you pass in the value and hopefully you get the correct result and as far as our setup we first need to understand how we can send those query string parameters from the postman correct so let me open up the postman and then of course i'm going to be looking for get all products so i'll just leave the testing one as it is so essentially in there we'll just hard code all the time but back in get all products not only i'm going to be looking for the product but i can go with question mark and then of course i can add key value pairs now we have two options either you can type it here for example you could say name is equal to john and notice how right away they're being added in this table as well so that's the second option where if you don't want to do it in the url you can just set it up over here and what's really cool you can actually check and uncheck them and what that means is that if i go here with john and then of course i send again the name and if i don't want to send it then i can just remove it and if i want to take a look at the featured ones and of course this is going to be featured and as far as featured i want to start with true and then once we send of course now we just get back the message but if we take a look at our controller we should have access to those key value pairs in rec dot query so let's test it out i'm going to go with simple console.log just so we can see that we're getting data and it is sitting in rec and query and let's do it one more time from the postman so let's send it again we get back the hard coded result but take a look at our console of course i can see that i have the object and then in there i have key value pairs with whatever i'm setting up in a postman and once we have jogged our memory on query string parameters now we simply want to go back to the postman and i'll just use the featured and i'll show you in a second why i want to do that and then i'll send it of course and if i take a look at my app of course now i only have featured so now let's set up the logic where i'll remove the console log and then we'll still be looking for the products and we'll use define of course but in this case instead of hard coding instead of setting up the object and then passing in whatever key and then the value of course will pass in directly direct.query now we will refactor the code because there are some gotchas we need to be aware of but with the most basic setup we'll pass the query directly into the find and let's hope that we'll get some results so let's start the same way we'll go with const products and that is equal to await and then product then dot find and like i said we'll directly pass in rec and query and of course once i get back the results i want to also send them and then in this case i'm going to remove the message and i'll just say the same thing where i'll pass in the product as well as the length of my array so that way i know how much i'm sending so let me go back and then one more time from the postman and again the route is forward slash product not the testing one and now i just pass in featured because that is one of the keys that i have and as far as the value i go with true and then once we send check it out now of course we have the product and the amount of items is equal to seven so if i'll change this to false now of course i'll get a different set of values again let's just quickly cover the logic where we have access to query string parameters in reg.query and since we get back the object we can directly pass it into the find one and then since in this case i'm looking for featured and i'm setting it equal to true that of course returns only the products that are featured and then if we pass into false then of course we'll get only the product where featured is set to false not bad not bad i think our basic setup works pretty nice or there are some gotchas we need to be aware of what do you think is going to happen if in a query string params we're going to pass in some kind of value that doesn't match any of the values that we have currently in the model so remember when we're setting up the model we have name price featured and yadi area but what happens if i send with my request a page which essentially we'll do because that's one of the functionalities we want to add and i guess the best way to showcase that is just by going back to the postman and here of course i still have featured set to false now you can leave it you can remove it that's really up to you what i want you to do is go below featured and then just add another key value pair and then in this case go for something that is not in our data so in my case i'm going to go with page because like i said we use that later anyway and then you can come up with whatever value you want and of course i want to check it here and also as a side note just notice the syntax so if you're going to be setting this up manually in the url just remember that in between them you need to add this ampersand of course postman is already doing that for us but if you're setting this manually just don't forget so now once i send check it out of course i have no values why well if i navigate back and take a look at my product what happens over here well i pass in rec.query directly correct and without even cancel logging we already know that we have a object with featured set to true or false that is really irrelevant and then we're looking for the page with some kind of value now mongoose of course is like well listen i don't have any product where there is a page property and that is actually set to 2 1 or whatever so therefore if i go back and if i do the same thing with the testing one again i'll have zero values back so hopefully that is clear so yes this probably is going to work with the most basic setup but then as your filtering gets more complex there has to be a better approach and that better approach is for starters pulling out only the properties you want to apply to the find now what do i mean by that well i'm going to go with const then i'll destructure from reg.query and in my case i'm just going to be looking for a feature of course eventually we'll add more values but for time being i'm only looking for featured so i can add 10 000 more items in here in a query it doesn't matter i'm just going to be looking for featured and if feature is set to true then i'll add it to define and once we have successfully pulled out the feature out of the query so now of course we're only going to be looking for this value instead of passing this directly into a find a better approach is actually to set up a new object so in here i'm going to go with const and i'll call this query object and that is equal to a new object and now i'll use the if and i'll say if featured is true then what i want to do is to set up a new property in this query object so in my new object i want to set up a new property by the name of featured so let's go over here let's say query object feature that's the property name and in here i'm going to use the turning operator where i'll say if the featured is set to true then of course i'll set this property equal to true now then of course e is going to be false so let's go with featured and then we're checking for true so let's say over here true now of course we use ternary operator and then if this is true then we set it equal to true if not then of course we go with false and once i have this logic i'll save and then instead of passing reg.query what it will do will pass in the query object and then since i want us to be on the same page i'm just going to go with console.log and you'll notice that first we only set featured so we're not going to be setting the page and we'll only do that if it is actually passed e into the query so if it doesn't exist so if the user doesn't send featured then of course this logic won't be applied and of course this is just going to be an empty object and then we get all the items so let's test out one more time so now of course i'm going to go back to all the products and let's send and now of course i get back the value of 16 because i'm looking for all the products that are not featured but notice how the page is not messing everything up so in here i can clearly say yep featured is there the value is equal to false and this is the object that i'm passing e into define but if we have a different request for example if there is no featured and the user is only looking for the page of course we're not handling the page functionality we'll work on that later but for time being what happens we get all the products why well because we have empty object so hopefully this makes sense instead of passing directly reg.query we set up a new object and first we just pull out the properties we're interested so in my case i'm going to be looking for featured i'm going to be looking for name later on and hopefully you get the gist and then we'll check if the property is actually coming in with a request awesome we'll set up a new property on our query object and then of course there's also going to be some kind of functionality in this case it was just straight up turning operator and then instead of passing that property directly we'll pass in the entire query object and that way of course we can avoid that bug that i showed you in the beginning of the video wonderful once we have the general structure in place so effectively once we have the empty object and then we check for the properties that correspond to whatever we have in the model now of course we can continue and add more functionality to our api correct so we want our user to search based on name maybe also based on price as well as rating and company and all that now i can tell you right away that we will purposely work on the number values so the price and rating and all that a little later because probably that's going to be the most complex logic of this project for now i want to work on name and company now company should be somewhat straightforward where we're going to check for the company so say hey is the company property on myrac.query and of course then we'll set up the value in the object and if of course we can find something then we're in good shape if not and of course we return nothing so let's go back and the first thing that i want to do is of course pass it from my postman so in here i'll remove the page hopefully it is clear what happens with the properties that are actually not on our model and then let's set up a new one and here i'll say company company and as far as the values well let me check since it's going to be faster so let's say i'm going to go with this one copy and paste and now i'm going to look for both i'll say hey get me where the feature is false and company is this one so let me send it here and now what you should see is only the product that matches company now of course not yet but that is the eventual goal so let me navigate back and notice again we only get the featured why because that's my logic so let's go back over here and let's say that we're also going to be looking for the company again not to be redundant because this company corresponds to something we have already in the model otherwise we'll have that mess where mongoose is going to be like hey listen what's happening i cannot find anything then of course we want to set up the logic and this is going to be as straightforward as it gets where essentially i'm going to say if the company exists then of course i just want to set up my property on a query object and the name of course will be company and i'll set it equal to my company the one that i'm pulling out of here so once i save and once we try one more time we should get different amount of values and of course in this case we get only six so now we get featured false and company is equal to ikea now if i'm going to pass in some kind of gibberish i'm going to say that i'm looking for a company bbb of course i'm gonna get zero results but that's what we expected so if we're looking for something that doesn't make sense just of course the user is not gonna be successful but if the user provides correct company value then of course we send back the list of products that correspond to that value and if you're wondering well where the user is going to know that info well that's why we have documentation so if you go back to this api you can see how they clearly explain what are our options and essentially how we can work with the api so now of course in our api we handle two things we handle featured and we also handle the company and once we have the first two down i think we already understand the pattern so let's try to do the same thing with the name and we'll start with the most basic setup where essentially i'm gonna go with a name and then whatever value i'm passing in meaning e in the query and then eventually we'll come up with more complex setup where we have the rejects because at the moment we need to understand that of course with our most basic setup we're only going to be looking for the product whose name matches exactly now what am i talking about well let me go back to the static one let me send it from here and i just essentially want to get one of the names and i'll look for this one and what you'll notice that with the most basic set effectively we'll get only the product whose name matches exactly so if i go here and if i send of course now i get only one product but if i mess it up here meaning if i just pass in the first value you'll notice that actually we get nothing so yes it's a good starting point where the value needs to match exactly but then of course we'll make it more complex and add rejects to the mix because that way we'll be able to just pass in some kind of text values and we'll get the product where that value is somewhere in a name so after my long rambling let me just go back over here where we have get all product and what is the property that we're going to be looking for of course that is the name and there's also something that i want to mention where nothing stops you from setting up your own api and saying here that you're going to be looking for the search for example like they have in the hacker's news api nothing stops you it doesn't mean that these properties need to match exactly now of course i'm setting up this way because it's much more easier later when i'm setting up the object properties so these ones definitely need to match whatever we have in a database but as far as what values we're looking from the query this is really up to you and again just to showcase that notice how they in here use query so we can definitely set up our own api with a query or search or whatever the only reason why i'm using the name is because it's just going to be easier when i'm setting up here in the object hopefully that is clear and then let's keep scrolling and we'll start like i said with the most basic setup we'll say if the name exists then i want to go with my query object of course name property and that one will be equal to the name so let me swing back to the postman and again now switch to get all products and since i'm just gonna get one value since at the moment my name is gonna match exactly i'll remove these ones i'll remove featured and company and you know what let me go to complete project and that way i can get the name right away and once i have the name now of course i'm going to be looking for the product and we want to add a new key and in here i'll call this a name and then i'm going to be looking for this value and then once i send of course now i'll get that one product and if we take a look at our query object of course this is what we have so we have a name and of course whatever value i passed in and since i have one product that matches that that's exactly what we get but if you take a look at the mongoose documentation you'll notice that they have these query operators now this one we'll use a little later when we set up our numeric filters but with the name i actually want to set it up as rejects and since mongoose is sitting on top of mongodb we can get those query operators from the documentation so let's search for mongodb query operators then let's navigate here and as you can see we have a long list of the operators now the one that we're looking for is this one the rejects one and essentially the setup is following where we go with rejects and then we have bunch of options now the one that we'll use is just case insensitive and then of course we just need to pass in the pattern so let me try it out back in our application and i think i'm going to start with the static one just so i can show you the setup and then of course we'll set up the more complex one as well so let me go here and i'll scroll above where i have the static product and i'll just set up some kind of value now since i'm not going to be passing this with a query just understand that eventually of course a value will be coming from the query so in here i'm just going to say const and let's call this search and i'll just type aaa now where i'm looking for the name instead of just passing in the value directly we'll set it equal to an object and then the setup is following where we go with dollar sign and then i'm looking for that reject query operator and then as far as the value i'll pass in the search again eventually it's going to be coming from our query here and then i also want to set up the options and therefore i'm going to go with dollar sign and then i'll pass in the options and i'll set options equal to i and you're not instead of 3a's why don't we go with just one so let's save it over here again the way it works we're looking for name property but instead of looking for entire name instead we go with rejects where essentially we're just looking for the pattern and the way we set up we go with rejects operator then we pass in the variable which of course again is going to be coming from our query and then we have the options and in this case i'm passing i which just means for case insensitive and once we navigate back to the postman and run it you'll notice that of course i'll get all the items where there is at least a a and then if we're going to go with a b now of course we're going to be getting a different value so now of course i only have 5. now in order to set it up e and get all product what do we need to do we need to look for a name we already doing that and then where we have here if name exists and then query object name we simply need to change this around where again you want to go with this one instead and in order to speed this up i'm just going to copy and paste let's scroll down and let's just say that if name exists then of course we'll use the rejects instead now in this case of course the search doesn't exist correct so we need to go with name so if you need to pause it here and write it from the scratch please do so because in my case of course i saved a little bit of time and just use the one from the static so once we save again i'm purposely leaving this one just so you can see what is coming in and if we hop back to all the products and of course now i'm just going to go with some kind of text value that is less than the entire name in this case i'm going to go with e then i will look for the company and why don't we keep the same one over here and then i'll also look for featured anvils and notice how slowly but surely now we can search for more options so in this case i'm looking for featured set to false company equal to ikea and then of course e in the name i'm looking 40. so i'm looking for the product where e is in the name and then once i send check it out now of course i have six of them and if you'll double check you'll notice that definitely e is a name the featured is set to false and of course company matches to the one that we have in the query string parameters beautiful at this point our users have three options for filtering featured company and of course the name eventually we'll set up numeric filters as well but like i mentioned previously since it's probably going to be the most complex thing in this project at least in my opinion we'll implement that last for now i want to switch gears and show you how we can sort our data first in final project then the general setup and then of course we'll implement it in our get products as well and something to keep in mind sorting does not affect the amount of items we're returning just the order in which they are displayed so let me navigate to my final project and then as far as the sorting notice right now i'm just getting them based on a date when they were created and of course since we added them dynamically meaning we pass in the entire batch that's why of course pretty much all of them are with the same date but if i want to sort them based on name what do i need to do well i need to go to the url bar because of course i'm not in the postman and then i go with question mark and then i just need to decide which property i want to use and first i want to go to sort and then let me zoom out a little bit and of course we either can go with name we can go with company we can go with also price and all that so let's just start here with the name and then once i pass it in again i'm going to get 10 values because i already have the limit there but you'll notice that the companies or i'm sorry the product are going to be in the alphabetical order so this is going to be my first one then i have the second one and on and on and on now if you want to sort them the opposite way meaning of course now we go from a to z but if you want to sort them z to a let me zoom in here and then you just want to pass in the negative sign here so where you have the name so that's going to be that parameter that you're using and then if you pass in the negative now you'll notice that the first value is the wooden table instead hopefully that is clear now what we can also do is chain them together so for example not only i want to look at the name but i want to also look at the price why would i want to do that well if i take a look at these ones where i have wooden desk notice how the name is exactly the same correct and the only difference between them is the price so if i add here a comma and then i say that i'm also going to be sorting based on a price and since i don't add the negative i'm just going to be looking for the smallest value first notice now i have the wooden desk with 15 dollars first and then i have one for 40. and you can probably already guess i'm sorry for all this zooming in and zooming out but i just think that it's important that you see everything that i type here if we go with negative then of course what is going to happen well we'll have one desk but the largest value is first now of course i can just sort based on price then i just remove the name and then if i go with price notice again we start with the smallest value and then you already know what happens if we pass in the negative now as far as the setup let's just go to the mongoose and i'm actually here where we have the queries and i'm looking for i believe it was over here yeah so general queries not find or refine by the or any of these functions just general queries keep scrolling keep scrolling keep scrolling and then in here they'll showcase two options that you can use now not for sorting but in general for filtering we have two options and we are using this one where essentially we set up the entire json but you also have this approach available as well and this is again just for your knowledge now what we're interested is this notice after defined what do we see over here we see limit sort and select and notice how they are chained after defined so first we set up our filter object correct and we passed into define but when it comes to limit sort and select we actually need to chain them after define and this is gonna become really important a little later on when we work with get all products so first i just want to show you the manual approach where we just go with sort but then when we set up all the products the fact that we need to chain them is going to be very very important so let me navigate back to our project and let's just start with the static approach so remove the search one not going to be looking for name and in order to make it interesting essentially i'm just going to pass in the empty object just so i can get all the product and then remember instead of the method i want to go with string and i want to pass in the name so i'll start simply with the name so if we navigate to the postman again the static now and if we send a request notice of course our response is going to be in the alphabetical order meaning we'll start with a and all the way to w at the very very end and as you can see i have 23 products now if i'll change this around and if i'll say negative here then of course once we send check it out now of course we start with the wooden table and same goes if i want to go with price and syntax is following where we want to create a space and then we type in whatever property we're looking for so in this case again we go with a name but it's going to be z2a and then we'll set up the price of course that is going to be from the smallest to the biggest value let me go back to the postman let me send and of course i start with a w correct but my price for the ones that actually match is gonna be the smallest one first so the smallest price first and then the largest one hopefully that is clear hopefully we understand how we can set up a basic sort so now of course we just need to implement that in get all products nice and once we're familiar with general info now of course let's implement that in get all products and we'll start the same way we'll have to pull this out out of the query since i'm interested in that particular property and of course the property that i'm going to be looking for is the sort one so if the sort is in the query then of course we're good to go but here comes the biggest gotcha where if we take a look at our code right now we are waiting for this one to complete correct and essentially when we go with this fine one we get back a query object but remember in order to sort we need to chain this correct we first go with find and then if you want to implement sort we need to chain it right after find now here's the problem though in my current setup yeah technically i can go here with sort but again remember there might be a scenario where the user is not passing in the sort so we want to do that conditionally and the issue here is following where you can say all right so i'm just going to go with let products and then i'll remove this sort from here and then i'm just going to go with if and then sort exist then of course i'll set products product equal to product and then of course sort and then pass in the value but the problem is following where since we have this await actually here in the product we don't have any more that query object that is going to be returned from the find one we actually already get that list of products so what i'm trying to say that in order for this functionality to work where we actually are chaining the sort if of course it is passed in by the user we need to remove this await and the way it's going to look like instead of setting up the products here we'll go let result and then of course we'll have multiple conditions in this case of course we'll start with sword but then there's also going to be one for fields and we'll also set up pagination hopefully that is clear and only then at the very end we'll get the product so we're going to go below the conditions at the moment we have only sort but make sure that it is always sitting at the very very end and of course in here i'm just gonna go const product is equal to my result and of course i wanna wait for it so i'm gonna say here await and then i'll remove this one so hopefully this is clear where instead of sticking the await over here since we'll chain the sort and fields and limit and all that at the very end of the query object we're getting back that's why we need to remove this await because this right away returns those documents and then set up the await when we have the complete result and i think at this point i can comment out the query object and i think i'll uncomment once we start working on numeric filters and now let's just work with the sort one so for starters let's just see what we're getting back because that way we'll have a better understanding of what kind of functionality we need to set up so let me just check it here a sort and then we want to go back to the postman we're not working in a static one we want to go to all the products and again since i want to get more data i'm just going to remove just keep in mind that of course you can still keep them you can still keep these query params as well because you will get the correct data i mean we saw that we're getting six heads but since i want to have more product i'll just remove them temporarily and we'll come up with a new key and in this case i'll say sort so let's set it up here sort and then as far as the values let's just start simply like we did with name and once we send let's just go back and of course now i can see that as far as my value i have my name now technically we can right away set up the sort and effectively we'll change this to the result but there's one gadget that we need to be aware of if we're sorting based on multiple parameters then of course the value that we can see in the console is going to be different so if i'm going to go here with comma and then price and you can keep the minus or you can just set up the price the result is going to be the same or essentially now we have two values meaning we have one long string but inside of the string of course i have both i have name and price and the idea is that maybe the user decides to chain i don't know three more correct so how we can split them up so we can get the correct values because if you'll try to pass this e into a sort remember the syntax is following where i want to go with a space in between them e instead of the comma so you're not going to be successful now what can we do well we can use the good old javascript where essentially we'll create a variable i'll call this sort list and that is equal to sort and i'll split it i'll say that i want to split it on a comma and then i want to join it back together so essentially i split it into an array and then from the array i join it back together in this case however just with empty spaces and now what we want to do is to go with result remember that is the query object that we're getting back from the find and we want to set it equal to result and then sort and now we want to pass in this sort list in there now what's also really cool is that we can set up some kind of default one so let's imagine the scenario where the user hasn't passed in the sort key but i actually want to sort it based on the time when those items were created how we can do that well we can simply go with else else and here we'll go with the result and that is equal to result of course again and we go with sort and now i'll just hard code the value just like we did over here however which property i'm looking for well let's take a look at our model all the way in the bottom we have what we have created that again since we created all of our projects pretty much at the same time technically you can argue that in our case it doesn't make much sense normally of course that's not going to be the case that's why this is going to work really nicely where we go result and then sort and then we pass in the string and i'm looking for created add and then once we save our functionality should be working so let me try it out i'm going to go over here i have the sort one okay awesome and then once we send of course we start with a products that start with a and then of course as you can see we get the rest all the way to w but if i'll change this around and i'll say that i want to go the opposite direction of course we can send the request notice again we have those two that have the same exact name but since we go here with this minus price that's why we start with the highest value so effectively we have the descending order but if we'll change this around of course we'll have the ascending order instead so that's how we can add the sort functionality to our api and once the sort functionality is in place next i want to showcase how we can select certain fields and i think the easiest way for me to show you that is going to the final project and then i'm just going to go with fields so that's the key please keep in mind that something that i made up the actual method name is different it is select but in the query variables we set up fields so this is just going to showcase which fields we want to see and as far as the values the same as with sort we simply need to pass here the properties that are in our schema and in my case since i want to see only the name property and only the price i'll type name price and hopefully you get the gist if you want to see some other properties just add comma and then the actual property so let's go over here and now of course you can see that in my response i only have the id which is going to be by default as well as the name and the price and if we take a look at the docs we can see that the method name is select and again we have these multiple options where if you want to go with just string you can simply say select and then pass e in the properties so let's try it out in our static one so let's move up we have the sort i think i'm going to remove the sort for now and we'll just say select and then in here i'll do the same thing i'll say name and price and once we go back to the postman which is always tough because it's all the way on the left hand side then i keep forgetting that now of course notice our response only has these two properties it has the two fields of name and price and if we want to implement that in get all products what do we need to do well first we need to come up with the name in a query string again this is what i said before where when it comes to the query string you are setting this up because you'll tell the user in docs hey if you want to search for certain fields then you need to add this property in the query string parameter if you decide that you'll call this shake and bake you're in charge you can definitely do so now in my case i'm not going to be such a rebel i'm just going to go with fields then we're going to keep on scrolling and right after this sort and you know at this point i think it's going to be very useful if i add some comments here and then right after sort but before the product would check for the fields again we'll say if the fields exist then we'll do the same thing where we want to split them up and of course join them back together in the process we'll remove that comma and then of course we just need to chain the select method so in this case in order to speed this up i'm just going to copy and paste this is now going to be a sort list we'll call this fields list and then instead of sort we're going to be looking for fields functionality is going to be exactly the same we split it up we join it back together and then as far as the result of course i don't want to sort it anymore i want to use select and i want to pass in the field list like so so go over here and then let's navigate to the postman and of course in this case we're not looking for the static one anymore we want to go with all the products here and then let's just add both of them together so i have the sword i'll keep that one and then i'll create a new key i'll call this fields fields and then as far as the values let's just say we're going to be looking for the company and also i just want to see the rating over here so let's pass these two and of course we'll notice that we only get the rating as well as the company in our response all right and once we have covered how we can select certain fields next i want to show you how we can skip and limit and by using both of those things you can actually set up a option for the user to choose a page now how's that going to look like well in our final project we can go here with limit and then just decide how many products you want to get back and i believe again we have 23 products so of course if you'll go with 30 then we'll just get all of them so just to showcase that notice of course now we have 23 but if i'm gonna go less so if i'm going to go with limit and then for example four then of course i'll get only four items and if i don't pass anything in then of course by default we'll get 10. that's where we have number of hits and that is equal to 10. so hopefully that is clear and as far as getting the correct page just like they have over here where you pass in the page and that is going to return that exact page number we have to combine limit with skip which is another option we have and before we go any further let me just showcase how is that going to look like in our manual setup so in here i think i'm going to stick with select i mean it can stay there it doesn't really matter and then as far as limit we simply need to go with a method and again we chain it and hopefully by now it's clear that ian get all products we'll have to do that before we await for the result and then in here we simply need to pass in the value so if i want to limit my response here to 4 then of course i can go back to the postman now i'm looking for the static one i send it and of course i'm only gonna get four of them now if this value is gonna be bigger than all the items i have of course i'm just gonna get all the items that i have in my list and essentially skip works exactly the same way but the difference is that it just skips the first items in response so let me just limit this by 10 and i'll make sure that we actually sort a to z so that way of course you can see exactly what we're getting back so let me go here and i'll chain that sort and i'm just going to be looking for the name and of course now we have a setup where we're alphabetically sorting our responses as well and in order to show you how so it works first let's take a look at our basic response so if we go here notice i'm getting 10 items correct because that is my limit and then i start with this item and then i have the next one next my next one so if i'm gonna go here with skip and for starters i'm just gonna say skip one notice that of course now we start with our second item so the item that was second in a previous response and if we keep making skip bigger you can probably already guess that we're just going to be skipping the items in our response so now of course we right away start with a letter b and once we understand the manual approach now of course we'll have to implement that in get all product and the goal is to use skip and limit to set up a pagination functionality nice and once we have discussed limit and skip now let's see how we can implement them to set up the pagination and in this case i'm not going to be looking for those values in reg.query meaning i'm not going to structure them because we'll set up the variables with the same name so i think it's just going to be easier if we'll go with rec query and then the page as well as the limit and all that so let's just scroll down again we're working right now in get all products i'll make this one smaller and we keep on scrolling keep on scrolling and then right after the fields we want to set up three values we want to go here with const and page so this is what the user is going to pass in same as they have here notice we go with page and then we just set up the page number now by default i do want to set up where we get the first page that's why you go here with page and then remember whatever is coming from the rec.query actually is a string and again just save some time i'm not gonna cancel log because we did the console.logs before and notice page is actually two correct but it is a string of two so of course before we do anything we need to turn it into a number so let me scroll back down and then i'll do the same thing over here where i scroll to the page and then we'll start with the number and then i'll say that i'm going to be looking for rec query and then the page now if the user doesn't pass the value then i'll simply use the or operator and i'm just going to say that it is going to be equal to one and the same is going to be for the limit i'll say that yes in the query there might be a limit since again it's going to be a number i need to use this number meaning since i want this to be a number but it's going to be a string we need to go with number and then we pass in rec query and then limit and if no limit is passed then we go with 10. that's why in a complete project you'll see this one where by default essentially we're just getting back 10 products hopefully we are clear on this one so if the value is passed in awesome we'll use this value if not then we have some defaults and now of course we just want to set up the logic and the way we set up the logic we go here with const skip and that is equal to page minus one and then we multiply this by limit and i'll show you with actual comment example just so we are on the same page so i'll set up the skip and now of course i just want to chain the skip and limit to my result remember we're still working on the result so once i have all of this functionality in place then we'll simply go with result is equal to and then we go with a result and then we change the skip we pass in the skip variable and then we chain limit and of course we pass in the limit variable now it's going to be kind of hard to see in our response so let me just set up some comments just so you understand how everything works so at the moment we have 23 products correct so if i decide to limit my response to only seven items how many pages i have well we need to divide 23 by seven and effectively we'll have four pages so we'll have seven seven seven so that's going to be 21 and then the last page actually is going to have only two items so we have total four pages and the way the logic works is following where the user will pass in some kind of value so maybe for the page is gonna go for 2 because remember by default it's always going to be 1 and then we multiply this by the limit that's the key over here so if we just have a default page we'll have 1 subtracted by one of course that is going to be zero and then multiplied by the limit still gonna be zero so effectively we'll skip zero items and then we'll just limit our response to seven however if the user is going to be looking for the second page then of course we'll have 2 minus 1 so have value of 1 and that is multiplied by the limit so in this case since i'm looking for page number two i'll skip seven over here and then i'll have the limit of seven so that's how i can see the second page and in order to showcase that let me just go to the static one and i want to get all the items just so you can see over here and i think i'll keep this as name and price like so and i'll sort this based on name and then let's do the same thing here so let me send it this is my entire list and then if i go to all the products now let me set it up everything correctly where i do want to still sort and i actually want to start i guess with a name and then i'm going to remove the price i don't really care about that i think so i mean let me just double check so select yeah so i'm only sorting by the name so let's see let's see so we have products i'm only sorting by the name and then when it comes to fields i only want to see name and then price and by default of course we're only going to get 10 because we already have that limit of 10. so therefore let me add here limit and i'm just going to go with a limit of 30. of course that is way more than we have the product so now of course i'll have all the products if i check it out here i have 23. now if i'm gonna be looking for page number two and i'll set up the limit where i wanna see only the four items or three or two or whatever then of course you'll notice that in here effectively we'll just skip whatever items we have in a limit so in this case if i go with limit off to just to make it simpler and then if i go for page number two so here we'll pass in the value of two you'll notice how we'll skip the first two items and we'll right away go for this one the albany sectional so let me send it here and check it out now of course we have albany sectional and i purposely set them up both the same just so you can see how it works so now of course we're looking at this page and as i'm changing the limit i'll be changing how many items i'm getting back and how many items i'm skipping and then when it comes to page of course it affects the amount of items we're skipping as well because if i go with three then of course we will skip two times whatever is the limit and those are the items we're skipping and of course that is going to return us that third page all right we're almost done with the project functionality the only thing left is to set up numeric filters or in other words provide a option for the user to search based on the number condition for example get only the product where the price is more than 30 or less than 30 and hopefully you get the gist but since there's going to be quite a bit of logic i will split this up in multiple videos and hopefully that way you won't be overwhelmed now just to showcase how is that going to look like i'm going to go to my final project and in here i want to go with numeric filters and of course i'll explain why we have this type of key and then we want to go with whatever property we want but of course it will make more sense if we're just going to go with the properties that actually have numbers as values so in our case of course we have price and then we'll go greater than and then of course we'll pass in the value so since i'm not using sort it's probably harder to see but it's definitely only the product where the price is more than 30. now just to showcase that let's go with ampersand let's add short and let me zoom in and then we're looking for the actual value and of course in here i want to pass a and d price so say here price and then let's check it out what we have of course we have 31 then 39 and on and on and on so this is how our api is going to look like now as far as the mongoose we'll have to use again those query operators and in this case for the greater one we go with dollar sign and then greater than and the same goes for less than but of course here we type lt now i'll show you all the ones that we're going to use in the next video now let's just try it out in our manual setup where we want to navigate back we're looking for the product and at the moment i have fined so let's go with price so let's go here with price and we set it equal to an object then we're gonna go with the dollar sign and then we'll pass in sorry not get gt so that's going to be greater than and then of course as far as the value well let's set up the same 30. and once we save of course and if we go back to our static one we should i mean we should let's see so at the moment i find name price and for some reason not returning any kind of value so let me send it one more time there must have been some kind of bug and now of course i can see only the items where the price is more than 30. and just so we can keep on practicing i'm going to go with sort and place here price let's see so that should be the ascending order and you can clearly see that we start with the product where the price is more than 30. so that is the manual setup and that's the general idea and now of course we can start working on get all products because in here we'll have way more logic nice and before we start typing away in get all products let me just showcase where i got the idea from and what are we actually shooting for and it's not going to be a surprise where i'm using again my api and as you can see here the key in the query string is numeric filters that's why we use the same one and then as far as the options of course they provide following so these are the ones where they have numeric values correct and we'll do the same so therefore in our case we'll just have one for the price and one for the rating and as far as conditions we'll notice how they use actually more user-friendly ones correct the ones that we're using in the final one and if we take a look at the mongoose one of course they have this dollar sign greater than and less than so pretty much that's going to be the biggest deal converting these user-friendly ones that we can simply pass in the url to the mongoose ones and in order to do that we'll have to do a little bit of regular expression magic but don't worry the code is pretty straightforward and of course i already got it for you and first thing we need to decide what is going to be the name for the key in the query string parameter and again i'll copy my favorite api at least for this course and i'll name this numeric filters so say here that i'm going to be looking for numeric and then filters now once i have access to the numeric filters i just want to scroll down and we'll do the same thing where again we'll set up a if condition and in this case i'll uncomment the query object because there's going to be times where i do want to showcase what we're getting back and let's just say with numeric filters and then as far as what i want to pass in well first let's go to get all product and again just to kind of keep this nice and sweet i'll remove rest of them and then at the end if we want we can add all of them but i'll just remove these ones and then we want to go with numeric filters because that's the name that i came up with meaning that's the one that you'll showcase in documentation and then as far as the values well let's simply go with price is bigger than i don't know 40 and then comma and what was the other one i believe that was rating and then let's set rating bigger or equals to four so let's send it to all our products and of course i didn't save it very very smart so let me go back over here i'm going to go with log and actually i didn't cancel log it either so let me look for numeric and we're going to be looking for of course the filters if they exist we want to console log them so let's go back over here and now of course i have empty query object because i didn't pass anything in and here i have one string i have price is bigger than 40 and rating is bigger or equals to four and the first thing we want to do is set up the operator map now what does that mean you'll see in a second so in here let's go with const operator and that map and in here i want to map the user-friendly ones to the ones that are understood by the mongoose so i'll say bigger than and then as far as the mongoose it understands the dollar sign and then we have greater than and once we have the first one of course we just want to add the comma and i'll copy and paste this four times and as far as the second value i'm going to go with greater than or equal and when it comes to mongos we just need to add this e at the very end then as far as the equal well we simply go with equal sign and then here we say equals and of course we'll do the same thing with less than and less than equals so in here let's go less than less than equals and as far as the mongoose values it's lt and then lte so once we have the map then this is where the regular expression magic happens where first i want to set up the regular expression and then we want to run the replace method where we pass in that regular expression and if it is a match then of course we'll change the value from the user-friendly one that we're getting in the numeric filters e into the one that is understood by the mongoose and when it comes to regular expression we just go with const and i'll call this rejects noun is equal to the regular expression and this one i got from the stack overflow so please don't overthink it you can always find those values you really don't need to come up with them yourself and inside of the regular expression we just want to go here with b and then set up the parenthesis and then you just want to pass in all of these values separated by the vertical bars so in here we go with less than then greater than and hopefully you get the gist and once i have all the values then we want to add one more b so let's go over here we add b and then we're going to go with a g flag and once i have my regular expression then i want to go with the replace method where essentially i call numeric filters which of course is going to be my string and then i'll pass the regular expression and if there is a match then of course we'll convert from the user-friendly one to the one that is understood by the mongoose so in here let's call this let filters and that one is equal to our numeric filters then we go with replace method and then as far as the first argument we want to pass in our rejects and the second one will be the callback function if there is a match so what we could do here i can access the match if there is one and as far as the functionality well i want to take this match and then i want to get the value that corresponds to something that is understood by the mongoose so here i'll return a string and i'll purposely use the template literal here and i'll purposely also add these hyphens and you'll see later why we want to do that so there's going to be two hyphens one at the start and then one at the end and then we want to access the actual value and now i want to go for my operator map and then i want to look for the match and hopefully you understand how this works so essentially i have the object object has the properties correct and then if there is a match over here then i just say hey get me that key and effectively i will swap the values and just so you can see how everything works instead of numeric filters why don't we look for the filters over here and then let's go back to the postman and send a request one more time and now of course you'll see the result so notice instead of this one where we have price is bigger than 40 and rating is bigger or equals to four now of course we have this we have price and then this is going to be that amongst value and the same goes for the rating and since i don't want to overwhelm you we'll stop over here and we'll continue with the logic in next video we have successfully converted our values to the ones that are understood by the mongoose but we're not done because of course i cannot pass this one into my query object we need to do a bit more data massaging and the way it's going to look first i want to come up with options because if you take a look at their api like i mentioned previously you can only do that on certain properties because these properties of course have number values and essentially we want to do the same where i'm going to go with options and that's just going to be an array and here i'll pass into string values i'll say price and rating because of course those are the two properties that use the number value and then we want to go with filters and set it equal to the filters and first again we'll use the split method remember that's the method that's splitting string into an array and i'll say that i want to split it where's the comma so of course now i'll have two items in my array i'll have this one and i'll have this one hopefully that is clear and then after that we want to go with four each so now iterate over that array and then in the callback function i'll have access to that item again it's going to be a string of price and yada yada and the same goes for the rating and then we want to do more splitting over there and effectively i'm going to split it into array and then remember we also have array destructuring where i can pull out the values and i'm just going to set it equal to item split and remember that when we were setting up our regular expression i purposely added here these hyphens so now each item so price and the rating i actually want to split it on that hyphen so say here split it on hyphen and the way the array destructuring works instead of object where we say a specific property whatever i'm going to type here first is going to match this price because of course we're splitting on hyphen the second one is going to be of course my operator and the third one is going to be the value so in here i can just go with field and then operator and as i said not if you need to catch up on the array of structuring i have that video in my javascript nugget series so let's go over here with the value so this is going to be the actual value and then only if the field so only if the price and rating is actually in my options only then i want to add a new property on that query object so in here right after that i'm going to go with if and then the name is options and we can use this includes method and if it includes the actual field then inside of the block i want to go with query object and then i want to set up the field so now again i'm dynamically setting up the property on my query object and since we're cancel logging of course you'll be able to see that and then as far as the value well again we need to go with object of course so let's set it here equal to an object and then we go with operator again this is dynamic of course because this operator will change in one case we have greater than in other case we have greater or equals so therefore again we go with operator that is coming from here and then as far as the value well we're still getting this as a string correct so we need to go again with number and then pass in the value so now of course once i save since we're constant logging you'll be able to see actually what we have in a query object so let me go back let me send it one more time and what you'll notice is this query object we have price and of course we have greater than and as far as the rating we have greater than or equals so what's really cool of course now we get the correct values where we only get the ones that have the price bigger than 40 and rating is bigger or equals to four so if i'll change this around and if i'll just say that i'm looking for a rating that is bigger or equals to 4.5 and then maybe the price is going to be bigger than 90 then of course once we save check it out we have only how many seven products correct so that's how we can set up these numeric filters in our api and once we have the numeric filters in place we're pretty much done with the project hopefully everyone enjoyed it and i'll see you in the next one all right and welcome to our next adventure the json web token basics project so far in our projects all the routes were public meaning anyone can access them and use them however they please but of course that's not how we want to set up apps in real world i don't want random people to access my data and i bet you probably feel exactly the same way so how we can restrict the access well i'm glad you asked a very popular method is using jwt or json web tokens and for the sake of simplicity just think of them as long strings now of course they're way more complex than that but let's just not worry about that right now and the idea is following imagine we have two routes a dashboard and a login or register route now dashboard is protected so i can click all day long on get data but i'll have no access to the info and only if i log in i get the token and only once i have the token i can access the secret info which in this case is just going to be a random number so let's try it out i have the dashboard clearly says here no token present and check it out not authorized to access this route and again i can click all day long and i can showcase that in the console where notice we're getting these 401 errors but i'll have no access to the data now in order to access the data of course i need to log in and of course this is just going to be a simple version where i just need to provide some kind of values if i won't provide the values then i'll get the 400 one so this is going to be a bad request and i still don't get the token so let's go up i'll say user name and i'm just going to go with my john and again you just need to provide some kind of values it doesn't really matter in a later project of course it will matter what we provide there but in this case we just need to provide something and only if i do that then i send it here notice user created so now of course i have no errors and also in the local storage i'm going to get the token now don't worry about the front end local storage and all that i'll talk about it in more detail later just think that you're getting the token and once the token is present and of course we can clearly see that here with the text of token present then we can make as many requests as we want in order to get our data again as long as the token is valid we are good to go now if again i'll try to submit and then i'll remove the token then again we're back to the not authorized this route now the reason why i made this project so simple and straightforward is because it's crucial that you grasp the main concept if you do i guarantee you you'll breeze through the upcoming projects even though they will be way more complex than this just always remember if a valid token is present in the request the user can access specific info now not all of the info of course you can only access the info that belongs to you so you cannot just randomly come here and get my data but still if the token is present you can get that specific data but if we have a restricted route so keep in mind that login is not restricted anyone can try to log in but if we do have the restricted route like we have with dashboard if the token is not present or it's not valid then the server in this case that's of course us will kick back the error response and that's how essentially we restrict access to certain routes aka certain resources and as far as the setup again we've got the folders final where you'll find the complete code and a starter where we'll do all of our work and when it comes to final you'll be able to spin it up once we cover gwt or json web token basics since you'll need to set up a variable in.env and when it comes to starter all of it should look very familiar and like i promised in a previous video in order to save some time on a boilerplate i already set up a basic express server for you so let me install dependencies and then i'll show you our app.js so let me zoom out i'll open up my terminal i'll clear everything and then of course first i want to navigate to the star one so grab it over here and then we're gonna go with npm install and then of course you will also spin up and pm start now when it comes to package json of course there are few other packages as well and i'll talk about them once we get there and when it comes to app.js essentially first i require dot env and of course that is in order to access the env variables then we have express async errors and if you remember we use that package just so we don't have to set up our own async middleware then we grab the express from express and we invoke it and we set it equal to app then we're looking for two middlewares not found one an error handler one and if you take a look at the folder the middleware one of course you'll see the error handler this is the one that we used all the way in the project number three this is essentially what we set up where we have the custom api error and of course we're looking for that instance and then if that is the case then this is the response if not then we just send back the 500 one the generic one and of course since we're using our own error class of course we also have it in the errors so if you take a look at the custom error one of course you can see that we have the class that is extending from the error and we'll do that because of course there's going to be some instances where we'll implement our own class instead and of course i'm importing both of them from the middleware like i said and then you can find the other one the not found here as well and then we'll also work on the authentication middleware that's what we'll find here the empty file then we keep on moving and we can see that we have app.years so we implement the middleware and in this case i'm looking for a static one so essentially we're serving static files because this is where our front-end app lives notice over here again we have index.html style css as well as the browser app.js and then of course we have express json and that is simply because one of the routes is going to be a post route and i want to access request.body so i want to get that data that's going to be coming in and then of course we implement both middlewares the not found one as well as error handler one and then we have the port variable we set it equal to process.env port or 3000 and of course in the final one it's a little bit different i believe it's 5 000 just so we don't have the port issues meaning just so we don't have two apps trying to access the same port and then of course i have a start one however you'll notice that in this case we're not connecting to the database so i simply wanted to showcase how everything is going to work without database and of course the next project will implement the database because of course that will add an extra layer of complexity and of course in here i just call app.listen set up the port i set up the console.log and if there is an error i log one now if you're wondering why i kept this db folder with connect1 just so you don't forget the setup again in the next project of course a major part of the application is going to be setting up everything once the database in this case i just wanted to showcase how everything is going to work in isolation and if you can see server is listening on port 3000 you can bravely navigate to your browser and we're looking for localhost 3000 and of course you'll see the app now nothing is going to work i can guarantee you that because of course we have no routes but you should see the ui so you should see the form as well as this g brush here in the bottom and if you do then of course we're in good shape and now we can start working on the project beautiful and once we're done with the setup next i want to set up our two lonely routes so we'll have one fake one for the login register and sign up and please understand that of course in the following projects there's going to be a huge distinction whether we're registering or we're actually just logging in but in this case we'll jam both of them together because our main concern is going to be that jwt or json web token and as a quick side note in the following videos when i use term jwt of course i'm talking about the json web token and then basically what we want is to set up those two routes and we already know how to do that so of course we have the routes folder in there eventually we'll have the router and then we'll also have the controllers so in this case let's just start with controllers so i'm going to go here with const and effectively i'll set up both of these functions and i'll go with this sync because remember we have the package that handles that the express async error so we don't have to set up the try catchers or our own middleware and we can simply go with rec and res and as far as the response we'll just go with the res dot and then send and here i'm just going to say fake login register and then of course d sign up and like i said normally of course there's going to be a difference whether we're logging in or we're registering however in this case we'll just mush all of them together and then we'll say we're out here that's for the login and when it comes to dashboard this is where we want to share that secret or authorized data so let's just say here dashboard and that will be equal against your sync rook and res and here let's do it a little bit more interesting where i just want to set up some random number and i'll call this a lucky number and of course that will be equal to math random which is coming from the javascript we'll multiply this by i don't know maybe 100 and then let's wrap everything in the math floor and essentially we should get the random numbers between 0 and 100 and then once we set up the lucky number let's just go with the res dot status and of course eventually this route will be protected but of course for time being we'll just go with res dot status 200 and then i'll say json and we'll be sending back the object i'll say message here and eventually it's going to be the name of the user and therefore i'll place everything right away in template string but for now since we don't have the user i'm just going to say john doe and then the other property on the object is going to be a secret so let's say here comma secret and again we'll use the template string and we'll say here is your authorized data your lucky number and then of course we'll access the variable and once we have all of this in place once we have the first string as well as the second one with lucky number now of course we just want to export them and i think for now i can just close the console as well as the sidebar and we'll just go with module exports and of course we're exporting the object and we're looking for two functions login and dashboard and it looks like i made a big old doozy where essentially i set up my code in the router instead of the controllers my apology so take all of this code cut it out from the routes and you're actually looking for the controllers we copy and paste and then back in or out of course this is where we want to set up the router so in here we're looking for express just like we did before we go with require we're looking for the express package of course then we want to set up the router so const router is equal to express.router router we invoke it and then we're looking for both of the controller functions and those are login and dashboard and both of them are coming from the controllers so hopefully you're able to fix my bugs and essentially we want to go two levels up and then we're looking for the main and then once we have all of this in place eventually there's going to be a middleware for authentication as well but for time being we'll just go with a router and then in here let's go with dashboard first so dashboard and this is going to be a get route and we'll simply pass in the dashboard controller now the login one is going to be a post one because of course we want to get those user credentials the username as well as the password so we go here with router then route then forward slash login and of course in this case we go with post method and then we'll pass in login and then last thing we want to do is of course export this so module exports and we set it equal to the router and then once we have all of this in place we go back to the app.js we're looking for the main router so i'm going to go above both the middlewares and i'll say here main router now that is coming from my route so require and it's in the same folder essentially it's in the root so we simply go with forward slash we're looking for the routes and more specifically main and then where we have the middleware for not found one and all that above it we'll just go with app.use and again what is going to be that root endpoint well in my case again i'm going to go with api and then version one because that's the setup that i have of course e in the postman and then of course we'll just set up that every time we get a request on this root endpoint we'll just go with main router so we go with main router and of course in the main router we have the dashboard so that one will be api version one forward slash dashboard and then for the login you already can imagine that it's going to be api version one and login and once the basic controllers as well as the routes are in place now of course we can move on to our next task nice and once we have our basic controller setup in place now let's also test it out e in the postman so in here we want to go with another collection and of course i'll give it another name and i'm going to go with 0 5 and pretty much the same as the app name so say here jwt basics and then in here we'll have two routes one like you just saw is going to be to get one and we're just going to be looking for the url then we'll go with forward slash and then we're looking for the dashboard of course so that's going to be our get route once we send the force we should see hello john doe yadda yadda the lucky number is 90 and notice how every time we send of course we'll get a different value and this is done on purpose just so you can see that we are getting a new request out and then of course i just want to save it so let's say over here and of course i want to save it here in my latest collection and then i want to do the same thing with my other route with log in one but of course that one is the post one correct so let me close this one and we'll just start with post then we're looking for the url and of course the route is logging here and just to jog your memory when it comes to the post route of course we want to send some kind of data to the server because effectively we want to create a resource on a server so therefore we go with body we'll go with raw and we'll set it equal to json and in here let's just go with username because this is what we'll be sending from our front-end application as well as the password and of course since we're just testing everything out we can go with whatever values you want and as a side note in general we'll only check if the values are provided now in the following project of course this is where the things are going to get way more interesting than that but for now you just want to send username and then comma and of course the password and as far as the password i think throughout this project i'm just gonna stick with secret and then once we send of course we have fake login blah blah blah which means that everything is correct and once we have tested both the routes and once we have properly saved them in our collection so here let's just call this login register and of course we can start focusing on the real logic therefore in here i'm just going to save it and we can start working on our next task and before we continue let me just give you a big picture of what we're about to do so first we know that we have a post route the login one and essentially since we want to log in or register user in this case we're going to be looking for two things we're going to be looking for username as well as the password and we already know that it's going to be available in reg dot body now if both of them exist we want to create a new jwt if not then we want to send back the error response then we want to say hey listen please provide email and password now if we're good if we create a new json web token then of course we want to send it back to the front end since frontend needs to access it in order to send another request in order to send the get request where essentially we display this secret information and on our end we want to set up the authentication so only the request with jwt can access the dashboard otherwise if you go currently to our front end notice and click here and i can actually access the data but that's not what we want what we want on the front end here or from the postman doesn't really matter but of course with front end it's just easier to see we want to provide username and password and only if both values are provided then we get back the token and only with our token we can make a successful get request and eventually display our secret data on a front end otherwise we get an error since the dashboard route is restricted and only accessible by authenticated users or in other words only by the requests where json web token is present and if we take a look at the comments the first thing we want to do is check for username and password and since it's a post route we already know that data is going to be indirect.body so here we go with const and then looking for both things username password and this is going to be the case where i will log them out so i'll set up here log and i'm going to be looking for both user name and password this is the case where you can send those requests from the front end but i highly encourage you to do that from the postman first and only do that later once our jwt functionality is in place so my case i'm going to navigate to my postman i'm looking for the login one i have the body yeah that's awesome and then i'll send it and back in my application if i take a look at the console of course i have john and secret there also could be a case where the user is trying to log in with just empty values correct so he or she can send this type of request and now on the console i can see that i have nothing and before we issue the token which eventually will allow the front end to access the route i want to check whether the username and the password have been provided now eventually once we work with database effectively we have three options first option remember when we use mongo's required validation it checks that for us if the value is not present it simply spits back the error so that's definitely one route that we can take once we introduce a database but in this case remember we're not connecting to the database another option we have is to set up the entire additional layer of validation which is going to be sitting in front of all of our requests and in order to accomplish that task we'll utilize another package by the name of joy but i only want to do that in a later project once we have a solid understanding of the json web tokens now the third option is actually checking for both of these values over here where i can say hey if the username or the password have not been provided then i'll send you back a a response now in our case what's really cool we have that package that wraps all of our routes and we simply want to throw a error what error well our custom one where we say hey listen you did not provide both values so therefore we'll send back a 400 response which essentially is a bad request so let's try it out i'm going to go back to my controllers and here i'll say if and then if there's no username username and the setup let me move these ones up and i'll add that comment check in the controller in the controller and once we're done i'll actually show you how we could have used that in task manager as well so let's go down and then we have username if it doesn't exist or if the password doesn't exist so essentially if one or both are missing then we want to throw that error why well because that's what we can do since we have that express async errors now what error are we looking for of course that is our own one so in the controllers what we want to do is import our custom error so let's go here with const custom api error now that is equal to require we're looking in the errors in this case and more specifically we're looking in the custom one and if the user hasn't provided the values of username and password then of course we can simply throw a new error and remember this is going to be handled in our own error handler middleware correct the middleware that we set up it's going to check for our own api error and if that is the case then we'll send back the status with the status code as well as the error message so now we simply want to throw new custom api error my apologies i started typing error actually we need to go with custom api error and here we'll say please provide email and password and as far as the error code it's going to be 400. so 400 stands for bad request and once we have the code to throw the error now i can remove this cancel log and let's just go back to the postman and test it out so if i haven't provided anything i should have please provide email and a password and status code should be 400. again if you already forgot how the custom api error works and all that please go back to the previous project i believe we set it up in task manager where i covered all of this e in great detail so essentially if these two values are not provided we have three options we can either use and you know just so it's less confusing i'll write here mongoose validations or we can set up another validation layer with the help of package by the name of joy which we'll do later or we can simply check in the controller and just to showcase if you take a look at the task manager so remember that was our third project where we essentially just started working with database more specifically if we're looking in the controllers and then create task remember we handle this with the help of mongoose correct because if you take a look at the models you'll see the name and this one is set to required now the same way we could have just checked e in the controller we could have just said okay check if the task exists if it doesn't exist we throw the error in this case it was a little bit different we used next since we used our own async wrapper the general idea doesn't change we're still throwing the error and if everything is great then we're creating a task and the only reason why i'm telling you all of this is just so i understand that you have multiple options you're not limited to just setting up the validations in the mongoose yes you should do it it doesn't mean that you should skip that part just be aware that there's extra layers of validation that we can add and in our case we simply set them up right in the controller so if the username or a password is not provided just throw the error which gets handled in our own middleware in the error handler one and here we just check for the custom api and then we send back the response and of course if that is the case we don't send back this string we send back the error all right we check for empty values now what well now we need to create a json web token and send it back but before we do that let's back up a little bit and take a look at the big picture one more time so far we have been setting up all our routes in the following fashion as long as the endpoint exists user just needs to make a request and our server will send a response but that's about to change from now on we'll have two types of routes the public ones accessible by anyone and restricted ones accessible only with correct signed jwt or json web token so back to our app if the user provides correct credentials meaning in our case of course those are just some values in the username and password we send back the signed json web token and in order to access dashboard wrote he or she basically a frontend needs to provide the same token otherwise we'll kick it back with an error response and before we analyze the structure of the json web token let's talk about some big picture things first and let's start with general concept json web token is just a way to exchange data between two parties and probably the most common example for such parties is a front-end app and our api now why using jwet is far better than just some random string simply because jwt has a security feature where we can be sure about the integrity of our data if the token passes the validation it means it's the same token we sent to the client and the data wasn't tampered with second for now don't worry how and where the front end will store the token i'll discuss it in more detail in a few videos and third please keep in mind that one of the features of http is that it is stateless and that simply means that server does not know or you can think does not remember any previous requests sent by the same client and as a result yes even after the first second or even the 200 successful dashboard request frontend will still need to provide the valid token otherwise the axis will be denied remember how i suggested to think of jwts as long strings well of course it's way more complex than that so now let's spend few minutes on the jwt structure and then of course we'll dive back into the code and a very good resource is cite by the name of jwtio again the url is jwt io and more specifically we're interested in two pages the introduction one and the debugger and i'll start with introduction and i'm not going to read the entire thing line by line that just seems a big waste of your time but i do want to point out some things here and there as always if you are interested in learning more you know already where to find it and the first thing that i want to point out is this sentence where it says this information can be verified and trusted because it is digitally signed so this is what i was saying in a previous video essentially we do that using the secret and the algorithm and we'll learn more about them in a few seconds so let's just keep on scrolling they say when you should use tokens okay and this is going to be the structure for the web token and like i said the result is going to look like a large string but of course it's way more complex than that and essentially in the json web token we have the header payload as well as the signature and when it comes to header consists of two parts and one is going to be the type of token and of course we're going to go with jwt and the second one is going to be the algorithm that is used of course to create that signature then this one gets encoded with base64 url so we'll code this one and then we have the payload in the payload this is where we'll place the information and as an example we can place here the id of the user that just signed on or logged in or registered or whatever then we send back the token the entire token with that payload back to the front end then the front end sends it back to us and then when we decode we get that id and essentially what that means is that if the user has some kind of resource we access right away resources that belong to only that user so essentially if you create some kind of resource only you can access it or modify modified or whatever then we keep on scrolling keep on scrolling and i'll talk about the payload of course when we actually create our own token this is just an example of what we can send back again this also gets encoded with base64 url and then lastly we have the signature and as far as the signature this is where the algorithm is used the one that is specified in the header and then we add here the secret to sign our token and as far as the secret this is something that we'll have to keep on the server and again i'll talk about when we actually create our own signature so once we set up our first token then i'll talk about it how and where we should store the secret value and the idea is we have the algorithm we have the encoded header as well as the payload then we take the secret string value that is always going to be only on the server and then we sign this one and then once we sign this is going to be a result so essentially this is what we're sending back to the front end and after that we have a bunch of useful information of how we can send back the token from the front end and this is something again we'll cover a little bit later once we already create our token so we'll swing back and i'll discuss what is the better and all this cool stuff and as far as the structure i think we're pretty much done i just want to showcase in debugger that of course we have the token like i said this is the signed token the encoded one and this is what we're sending back to the front end so this is what the front end will receive now once we decode there you go you'll have information about that user so you'll have some kind of id maybe a name and when it was issued and of course later we'll do something with that data so this is that id that we're looking for the user id and then we can use this id to access the database resources and all that cool stuff hopefully we're clear on the structure so now we can take a look at the package we'll use to sign and decode our tokens when it comes to signing and decoding our tokens there are quite a few packages out there so you definitely have plenty of options but for my projects i usually use package by the name of json web token of course if you're using starter i already installed it for you but if you ever want to use it in your own project just run this command and as far as the docs since we'll use only two methods i'm pretty sure i won't return here but of course if you ever need more info just utilize the search engine nice and once we have discussed the general principles of jwt now let's try to issue one in the project and first what we want to do is import the package and again the package we're looking for is this one the json web token and of course we want to assign it to some kind of variable so i'm going to go with jwt is equal to require and of course we're looking for the package and once we have the package after the if assuming that both of the values are provided we want to create a new token and we do that in following way so we come up with some kind of variable in this case again it's going to be a token pretty straightforward and then we go with jwt so the package name and then we're looking for the sign method and then in the sign method we want to provide three values we want to provide a payload a jwt secret essentially is just a secret string and then the options now when it comes to payload you go with object and pretty much in here you can pass whatever you want sky's the limit now please remember one thing you don't want to send back some kind of confidential information so don't stick a password over here that is a very very very bad practice now what normally gets sent back well if we're creating a user a id is very helpful because then later on when we're authenticating the request we can check for the user if i'm creating a user and that user is i don't know checking for some kind of resources we only provide resources that belong to the user so in our task manager application we only provide tasks that belong to the user and as a result only the user who created task for example can view it or it and hopefully you get the gist so in here i'm just gonna go with username that was already provided over here so that's what i'm sending back and like i said normally send back the id but since we don't have the connection to the database i'll create a dummy one from scratch i'll simply go with id and then i'll go with new date and i'll say get time and let me just add a comment just so it's clear that this is only for demo and once i have both of the comments first i'll add the id and then i just want to mention here that when it comes to payloads it's a good idea to keep them small because the bigger the payload the more data you're sending over the wire and of course as a result for someone with bad internet connection the user experience might not be the best one so that's about it for the payload and then we want to provide that jwt secret so we go here with a comma and we right away want to set it up in our dot envy so of course we need to create one from the scratch and in the star we're going to go with new file dot env and then we need to come up with a variable name and in my case i'm going to go with jwt underscore secret and when it comes to value in this application i'm just going to go with something really simple as jw secret but let me grab the comment that i left here just for a demo in production use long complex and unguessable string value and when it comes to more complex projects i'll show you how we can create one so let me just take this one out and then i think i'll just leave that in the controller there right below the payload small comment where again you always always when it comes to production you want to have them long complex and unguessable in this case we're just cheating because i don't want to bother with that so we go with variable and then some kind of value and now of course we just need to go back to the controller here and then remember we can access it with process dot env and then more specifically we're looking for jwt and then underscore secret and if you're confused or just wondering why we're so fussy about this jwt secret string if you recall the json web token structure video this is the secret that is used to sign r tokens and therefore it's a good practice to only keep it on the server and make it more complex than our current jwt secret just keep in mind that if someone gets a hold of your key they can start signing tokens on your behalf and that's definitely not the spot you want to be in as you can see even in the docs they suggest your 256 bit secret and like i already mentioned in the following project i'll show you where and how we can set up a proper secret value in no time and then the last thing we want to provide is options and we're going to go with expires in option and i'll set it equal to 30 days and i'll come back and talk about the expirations and all that a little bit later so once we have the token now of course we want to change our response where instead of the string we're going to go with actual status so set it up over here 200 then that and of course we're going to be looking for the json here and then let's just add here a message and we'll say user created user created and this is the case where the front end is using that message so i strongly suggest keeping it the same way and then we'll go with token so effectively we have our token and now we just want to send back to the user so once we save we're going to go back to the login one and in this case i'll try one more time providing empty values and of course in that case i get back my error one but if i go here and if i say john and secret i should get back my json web token and of course i do and what's really cool if you take this value and just head back to the website and just copy and paste what do you know of course now i have username some kind of fake id and this is going to be the expiration so as you can see this is the payload that we're sending not bad not bad we signed a token sent it back to the front end now well first we need to understand how the request with the token already present is going to look like but before we continue let me just emphasize something since it's a backend course we're not going to dwell too much on do's and don'ts on the proper jwt storage on a front end yes of course there are best practices and don't get me wrong they are important but our current goal is to secure resource access on the server and therefore we're only really interested in how the request is going to look like so we can implement the correct functionality on our end and if you keep reading the introduction you'll see that a common approach on a front-end is to set up the authorization header in your request so of course in our case that is going to be a get request and then add the bearer schema essentially what that means is that we have the header by the name of authorization then we go with bearer and then space and then the token and in this video i'll show you how it looks like on the front end as well as the front end code and then in the next video we'll do it together in a postman and basically the idea is following where i have the username password and all that and i just go here with peter and then i pass in my secret and what i want you to see is the local storage because of course at the moment we have nothing in there and the idea is following where i will get back to token because of course i'm providing some kind of values in the username as well as the password and now check it out here i have token so now of course when i'm making that next request so if i go here with get data of course in my code i just grab the token from the local storage and of course i'm successful and if we take a look at the network requests so again this is going to be for the login this is to get the token and then of course as far as the dashboard just open it over here and notice the headers so we keep on scrolling the request headers blah blah blah and what we're looking for of course is this authorization one so that's the one that we want we have authorization then we have the bear and then of course we have the token and if you're interested in a code just navigate to browser app.js and first what you want to do is to look for the form event listener we're listening for the submit event and then in here i have try and catch and in the try and catch i'm using axiorys library with a post request and surprise surprise i'm sending this post request where to a login one and what am i passing in passing in username and password and what happens if i'm successful notice this line of code we go with local storage set item token and then whatever i got back from the server so i right away save this token in the local storage now there's also a catch and in this instance i just removed the token now again this is just my preference just so i can demonstrate things but hopefully you get the overall idea that of course on the front end you'll store this token somewhere and then of course when it comes to actual request i have the button i have the event listener the click event listener and then i'm issuing a get request of course where is it going it's going to the dashboard and the way we add the headers again this is just for axiorys library but the idea is going to be exactly the same for fetch or any other ajax library where you'll go with headers and then of course the name is authorization and then like i said we go with bearer schema and then we add the space and then we pass in a token and as you can see i'm getting this token from the local storage and of course let's take a look how we can send the same request with a postman and once we have discussed in theory how we can send back the token let's try doing that in the postman so in a login every time i send a successful request meaning where the username and password are valid values instead of empty strings then of course we're getting back the token and of course all this time i'm creating with john but just understand that every time we're getting that unique token and what we want to do take this token so copy this one and of course don't worry later we'll set it up with different usernames at the moment there's really no need for that and then back in the dashboard so in our get request we're not looking for the body we're looking for the headers and in the following project i'll show you how i can do that dynamically in postman because of course when it comes to bigger project is going to get annoying really fast if you have to all the time copy and paste those tokens just to test something out but in this project yes we'll do this manually so again we are in the dashboard that's the route of course it is get and all that and then we're looking for the headers and header name is going to be the authorization one then we want to set it equal to bearer that's the name and you have to follow this to the t so bearer and then copy and paste the token so now of course if we send yeah we get the value blah blah blah we have the number but what's more interesting if we go back to the dashboard and if you log request headers you'll see something really cool where if i go with request and like i said headers now let me send one more time again the token is still valid we have 30 days so everything is going to work if i scroll up check it out we have authorization header and then of course i have the bearer and then this is the value and this is what we'll do in the following videos we'll extract this and actually validate it and if it is valid only then we'll send back the data with the actual username the moment of course we just have john doe but eventually we'll set up where whatever username gets sent back to the front-end well that one will send back here because that way we'll showcase that we only access the specific resources that the user has not just some random ones beautiful and in order to get to this value we'll just have to do a little bit of javascript magic and we'll also have to throw a few of the errors if the values are not provided so in dashboard first i want to assign that authorization header to some kind of variable and in my case i'm going to go with auth header and then i'm looking for a request and then of course headers like i said and then we're looking for the authorization one so once i have access to the header then i want to check whether it actually exists because maybe user is sending a request without the header altogether and if it exists whether it starts with a better and then the space again this is very very important that the syntax is exact because if it's not going to be exact then of course all of this loses the meaning so let's say here if and then off header so if it doesn't exist or the auth header and then starts with that's the method that we can use on javascript strings and in here i just want to say if it doesn't start with the bearer then of course we'll throw the error so if there is no authorization header or it doesn't start with bearer then of course we'll throw our custom error so i'll just add here bear and then the space now if that is the case what we can do well we can throw our own custom error and in order to speed this up i'm just going to copy and paste we're throwing the error and normally you're going to be way more awake than this but in this case since we're of course just testing the jwts i'll say here no token provided in that case if you hit some kind of roadblock at least you know where the error is coming from and when it comes to text normally it's going to be along the lines of invalid credentials to access this route and as far as the status code instead of 400 it's going to be a 401 so that is not a bad request that is actually the authentication error but again in this case just to make it easier if you need to debug i'm gonna go with no token provided and then as far as the error we're gonna go with 401 and of course in order to test it out why don't we go back and then i'm just gonna uncheck the authorization just so we can actually see what we get back and once we click check it out now we have message no token provided and what is the error of course error is 401 now if i go back to the authorization header and if i send now i can see something went wrong try again later that's interesting so let me double check my code and yes of course it starts with not start with so let me try one more time let's send and there you go now of course we have hello john though and of course the secret as well and once we have passed the first stage now i just want to get that token and we can access it in a following way where i'm going to go with cons token is equal to auth header and then we want to split it again this is a string so we split it on a space and we're looking for the second value and if you want to double check let's go with token and let's cancel log it just so we are on the same page so let's send one more time and as i know there's a tiny bug there as well and you should see in the console a token and i'm also going to fix it over here what i'm going to say your lucky number and once we have all of this in place now of course we just need to set up the verification where yes we got back the token from the front end however now we want to verify whether the token is actually valid and as far as verification goes something like this where if you take a look at the docs of the package the json web token one you'll see that one of the options we have is using try catch and then we just need to come up with some kind of variable name in my case i'm going to go with decoded and that is equal to the package so jwt now the method name is verify and here we need to pass into values we need to pass in the token and then the second value is that secret string so again we go with our process dot env and then the jwt and if there's some kind of error for example the token might be expired we'll handle that in the catch block and what do we want to do well we want to throw another custom error and this is going to be the case where i'll show you that vague response where again we'll throw custom error if we're not able to verify the token and as far as the response will say not authorized to access this route hopefully this is clear so we try to verify if there's any kind of issue we throw another custom error and in this case we go with not authorized to access this route and again the code is still 401 because that is authentication error and then of course if we're successful then we just keep on typing because all the data is going to be in this decoded now what data you might ask well let's go to console.log and let's check it out together so let's cancel log one more time let's send it here and now of course you can see that i get back my id username as well as other two properties issued at and expiration and of course all of this is coming from our payload the one that we passed over here when we signed the token so of course you can already imagine that if the name is going to be different for the user name of course this value will also change and by accessing that value now of course we can set up a dynamic response so what do we do over here we just say okay we have access to the decoded one so let's take our code and just move it up place it in the try block and then instead of just console logging i'll keep the random one and all that don't worry there's gonna be a little bit different setup in a second anyway but instead of john doe we'll go over here with decoded and what is the property that i'm looking for on the object of course that is the username so we just go back over here to the username and if i navigate back to the postman now of course once i send i'll get back to john so let's go over the steps in the postman first and then we'll try it out in the front end in our application so first let's go with login again i'll try to log in without providing the username for example i'll send it over here now of course i have please provide email and password so that was that first check so if we are successful here if i provide peter then of course i'll get back my token awesome and i can see that the user has been created then we want to go to the dashboard and where we have authorization header now i want to change this around where instead of this value again just make sure there's that space that's a big deal here we'll provide this value instead and now of course i have hello peter and then again some random lucky number and if everything works in a postman it should also work on the front end so let's try it out over here let's refresh of course we can see no token present and here i'll just try to get the token without providing the values and of course not successful so i get back the error and therefore i'm going to go with anna and then again some kind of dummy password we send it now we're successful user has been created of course i can see that token is present oftentimes the token is going to be in local storage and of course it is so now of course when we're making those following requests now the token is present so we're successful now we can clearly see our username and then we're getting those random values so all the following requests are going to be successful as long as we provide a token and since token is in the local storage of course we can always access it when we make it and then we're good to go now if we remove it and in this case i just set up the functionality that if the user tries to get the token without providing the values then i just wipe out the token in the local storage so if we go back notice it's actually empty now i'm not saying that that's always going to be set up on the front end it's just something that i used in this case so now if we go back again we don't have the token so we get this not authorized to access this route nice work we're actually done with the main functionality but just like in a previous project once everything is in place let's also work on some improvements which we'll use heavily in the following projects and first i want to set up the authentication middleware and essentially the idea is following where yes at the moment we have the dashboard route and in there we're successfully checking whether the json web token has been provided and of course if it's there then we send back the lucky number if not then we throw the error but we need to understand that in a more realistic application of course there's going to be multiple routes that use this functionality and what are we going to do are we really going to copy and paste for every route that needs it or it just makes more sense to take all this code stick it in the middleware and then just choose which routes need to be authenticated and of course the answer is setting up our own middleware so first let's go to the middleware directory in there you'll find auth.js and we'll just start very simply by creating a function that function of course is going to be a sync and we'll be looking for rec res and next and next is very very important because otherwise our whole cycle is going to break and then of course we just want to cancel log so in the beginning we'll just cancel log and then we'll set up the functionality let's go over here as always naming is really up to you i'm gonna go with authentication and then middleware and that is equal to like i said async then we go with request and response and then next because remember in order to move on to the next middleware which of course in our case is going to be a dashboard route we'll have to call next and i'm going to go with console.log then i'm looking for rec headers and then more specifically i'm looking for the authorization one i just want to check whether it exists and then i want to go next like i said and then of course we invoke it now we just need to export this so we're going to go here module and export and that will be equal to my authentication middleware function and now another million dollar question so where are we going to use this middleware now in a later project we'll actually use it on multiple routes but in this case we only have dashboard that needs it correct so as far as the login this is going to be for public access but when it comes to dashboard this is going to be protected by that authentication middleware so therefore in the router in the managers we're going to go here const and then of course i'm looking for my function and in this case i'm just going to call this auth middleware and that is equal to require of course then we had the middleware folder and the auth file and the syntax is following where where we have this get method before the dashboard i actually want to stick my middleware so i'm going to say auth and then middleware and i'll add comma so now of course every time someone's going to be hitting this route first they'll go through the middleware and of course in the middleware since i have next then i'll pass to the dashboard and in order to test it out i'm just going to navigate to the browser so this is where i have the working application and it doesn't really matter whether you're logged in or not just go here to get data and of course in my case i haven't logged in i have no token so therefore i'm getting back this not authorized access this route but what i'm more interested is back in my application in the console i can see bearer and that is set to null so now i know that all the requests that are going to the dashboard are actually hitting this off middleware first so now of course we just need to add the functionality and we'll be in good shape beautiful and once our bare bones setup is in place now we simply want to go back to the controller the main one and we'll need to copy and paste two things and again i'm just doing this just so we can get to the functionality and you're looking for jwt because of course we'll implement that functionality as well as the custom api error and as i said not in the following videos we'll work on more errors so essentially we'll create here more error classes so i'll have to do some refactoring as well but for time being we'll just grab these two lines of code we want to go back to the auth we want to make sure that the paths are correct so as far as json web token of course it doesn't really matter i mean that's the package we installed we just want to make sure that this path is correct and it looks about right so now of course let's go back to the controllers let's keep scrolling keep scrolling so of course that was the previous route the login one and as far as the dashboard we simply want to take this logic where we're looking for the header and if there's some kind of issue of course we just throw the custom api error then we get the header and if everything is great if we can verify the token then instead of setting up right away response in our middleware we're actually going to set up a property on a request object and the property is going to be user and then we'll pass it to the next middleware which of course is going to be this dashboard route so let's go step by step let me take these i mean what is it five lines of code take it out so everything up to try and catch you want to go back to the auth js now you want to remove the console log and just keep the next because that is very very important then back in the controller you also want to take the try block but we'll have to do a little bit of acrobatics here because i'll actually need these lines of code so let's go back over here take the try catch as well step by step and then copy and paste and here the logic is following where you want to remove this response with lucky number so these things go you want to cut it out and go back to your controller and set it up in the dashboard so this logic stays of course the same where we have lucky number we generate that and of course we only send that response if we're successful now back in the author js like i said we're still checking for the header we're checking whether it starts with bear if not we throw the custom api error that's why we import it over here then we keep on scrolling we get to the split we get the token and now of course we have try and catch where we are invoking the verify method we pass in the token that we're getting back as well as the secret one and then if we're successful then instead of sending a response since we're working in the middleware the logic is going to be following where i'm going to go with const and then i'm looking for two things i'm looking for id and the username here and that one will be equal to decoded so of course if i'm successful this is going to have some kind of value if not we'll throw the error and then if that is the case i want to go with and i'll just set it up to the object where i'll have id and username and of course once i have set up the user property with this object value now of course i want to call next so we'll move this next up over here and what happens in the controller in the request we'll have that user property and now instead of looking for decoded of course we'll look for the user now in order to make it a bit more explicit i'll actually cancel log it just so you can see where it's coming from so i'm going to go here with rec and user so you can clearly see that we're getting that from our middleware of course and then instead of looking for decoded we're going to go here for user and username now in this case i also need to add direct since of course i didn't destructure it so on the request object and i have the user property and in there i'll have the username as well as id and let's just test it out one more time to functionality so again i'm gonna be on localhost 3000 i don't have the token so now of course i shouldn't see anything in the console and i don't because remember we only get to the dashboard if we're authenticated so let's try it out here where i'll say peter and then again my secret password i'll submit okay i created a user token as present and then once i click on getting the data now of course i have hello peter and i'm getting the lucky number and now if i take a look at the console check it out now of course on the request object once we get to the dashboard we actually have the user with id and username peter and of course this is coming from our middleware where essentially again we check for the authorization header then we check for the bearer we split it up we get the token then we use try and catch because we want to run the verify method and then we pass in a token we pass in the secret and then from the decoded we get the id and username and since we want to pass it to the next middleware essentially we create a new object we say user object on the request and then pass it on to the next middleware and of course if we're not able to verify the token then we send back our custom api response and again the end result is following where you can set up whatever amount of route you want and in front of all of them you can just stick off middleware and then you don't have to repeat this code the code is sitting in one place and check for token if the token is not present then you just send back the error response and once we have the middleware in place now i want to switch gears and talk about the errors and if we take a look at our application at the moment we have two types of custom errors we have one for 400 that's going to be the bad request and then we have another one for authentication where of course we have 401 and technically we have been doing fine with just this one custom error but there's actually a better approach where yes we have custom api error that extends from the error so this logic stays the same but instead of just using this one class will actually extend from this custom api error and then for every type of error we have which again in our case r2 we have one for battlequest and the second one for authentication we set up two more classes and then in those classes we right away hard code the status code and i fully understand that this might sound confusing so let's just start working on it and in the process you'll see what i mean so first what you want to do in the custom api error just remove the status code we'll set them up in separate classes and then we want to create three more files and we're going to start with index.js and you'll see at the very end of the video why we want to use that then we want to set up two more and we're looking for bad request and we'll go with js and then i'll set up another file by the name of on authenticated and then of course it is js and then in the bad request what we want to do is pretty much take the code that we have in the custom error one pretty much just copy and paste because we'll just change some things around so copy and paste over here and then i want to close this one so i'll say close saved and then instead of the custom api error we're going to go with bad request that request and of course this is going to be extending not from the error actually it's going to be extending from our custom api error so let's go here with const and we're looking for custom api error now this is in the same folder correct so we just go here with the require and then we pass in the path so the path of course is custom api error and instead of like i said extending from the error we're standing from custom api error and then we still have the constructor we don't want to use the status code over here and as i said not you know what in customer i also want to remove it so we just have the constructor and super here as far as the message and then in the bad request this is where not only we have super method with a message but it will also go with this dot status code status code and we'll set it equal to some kind of hard-coded value now for the battlequest what value we're going to use well we're going to go with 400 and then of course instead of exporting custom api error we're going to go with bad request and now we simply want to take all of this code copy again just so we can save a little bit of time and paste in the authenticated one and then of course again i'll have to change some values around where this is going to be the unauthenticated error so let's go over here on authenticated and we'll call this error of course we're still looking for the custom one so we're still extending from this one now the status code is going to be 401 and here we'll also say that we're exporting on authenticated error and then we want to go to index.js and here we'll import all three of them the custom error the bad request as well as the unauthenticated and then we'll export them as one big object and you'll see once we start factoring the application why it's more useful so essentially if you want you can technically leave it the way it is just remember that every time you'll need to use one of these you'll essentially need to look for that specific file if we set up this index.js first of all you'll be able to look just in the errors because by default the index.js will be served and in there we'll have all of the errors so let's start here with const and then custom api error and of course i'm looking for the file by the name of custom api error then we copy and paste and we just want to change these values around so of course this will be the bad request one and then last one will be that authentication one and of course we just want to change these files around so this will be the bad request one and then the last one will be equal to our authentication one and then we want to set up the object we'll say module exports and that is equal to our custom api error and then the battery quest one as well as the authentication one now of course at the moment our imports are a little bit different but before we do that i also want to talk about the status codes so let's just fix the status codes first and then we'll do both things we'll import the proper error classes in our application and also right away set up the status codes using the external library all right so far in our application every time we need a status code we just type the number value which is kind of okay but there's actually a better approach and that better approach is using the library by the name of http status codes and of course we need to install the library so this is the code if you need it for your own project in my case of course i already installed in the stars so that's why it's available and then we simply want to get the status codes from the library and then this is an object and then as far as the properties we just need to look for the text values for example for 200 we're going to go with ok now if you want to take a look at the codes of course just keep on scrolling and you'll notice that if we want to go with 200 response of course then we just type okay if we want to go with battlequest then we just type it and this is going to be 400 and hopefully you get the gist and as a result we'll accomplish two things it's going to be easier to understand what is happening as far as our responses instead of juggling the 400s and 401s and all that in your head and the second thing of course we'll have more consistency so let's try it out and in this video i'll just try it out here in the error classes and then of course in next video when we'll be refactoring our code since of course we have different setup for the errors then we'll also implement those status codes there as well and what we want to do is go to the bad request and then below or above the custom api error again this part doesn't really matter we're just going to go with const and then we're looking for status codes now this is a named import so make sure that the name is exactly the same status codes and then that one is coming from our library http status codes and then instead of this 400 we're going to go with status codes and then we're just going to be looking for bad requests notice how they right away give you all of these suggestions again it's easier to read it's easier to understand what is happening and second we'll have the consistency and we want to do the same thing in on authenticated as well so let's navigate to this file again we'll copy and paste just so we can speed this up so copy and paste we get the status codes and in this case of course we're not looking for the bad request which one we're looking for unauthorized so let's go over here let's say status codes dot and then we're looking for the unauthorized one and once we have fixed the error classes using the status codes now of course we just need to hop back to our application and refactor it since of course our error handling has changed as well awesome and as far as the refactoring we actually need to work in three files we want to look for our middleware so of course that is going to be the other one so let me just close all of them for now and then let's start from the scratch so like i said we're going to be looking for the auth middleware that's the first one then we also want to work in the main.js we'll have to change the code here as well and then lastly of course it's also going to happen in the error handler so where we have middleware for her handler we'll have to change some things around here as well so first let's start in the auth chairs now what error are we throwing over here well at the moment it is custom api error but actually what error is it well of course it is the authentication error correct and we already have the class for that which has the unauthorized status code so what we simply want to do is look for index.js so of course this is going to be the errors folder and then more specifically we want to look for this error i'm just going to copy this value and then back in the auth now of course we're exporting as named exports so we need to change this around where i'll say okay i'm expecting here the object and this is not going to be coming from the custom error it's actually going to be coming from the errors copy and paste and now of course i just get the unauthenticated error and then instead of the custom api error we're going to go here and we'll say on authenticated error and now of course we don't need to pass in that status code correct we just need to provide the message so let's remove it over here and then we want to do the same e in the catch correct so the functionality is going to be exactly the same and just so we can speed this up maybe let me grab the first part over here and copy and paste and then again we don't need the status code we just remove it and we'll be in good shape so that's the first file we want to fix then we want to go to the main.js e in the controller and pretty much it's the same thing where at the moment i have custom api error but effectively what error i want to throw here well i want to throw the battery quest one correct pretty much everything after that is just for successful responses and i think i'm going to remove the console log since we already covered that and then let's scroll up again we want to change what we're actually requesting so in this case i'm looking for this bad request error so let's go back to the main.js and we'll set it up as an object over here and then again we're not looking in the custom error we're looking in the errors and keep in mind that since we're exporting as object if you have multiple errors we simply want to add comma and then just get them so now we're looking for bad request error and instead of custom api error we'll exchange it for bad request error we already have the status code so we can remove that and then finally let's go to the error handler one and in here of course i'm still looking for the custom api error so as far as the instance this doesn't change because both of them the bad request as well as the unauthenticated extend from our custom api so this will be still true the difference of course is that we're looking for the object in this case and we're looking in the errors that's number one and the second thing we want to do is get those status codes and that is coming from the http package so let's say here http status codes and in the if block everything is going to stay exactly the same because of course we're getting the status code from the object correct and then as far as the message it's also there but when it comes to this 500 you can change this around and say that we'll be looking in the status codes and this is going to be equal to the internal server error and when it comes to message i guess it can stay the same and with all of this in place let's just navigate to the browser and then let's test it out let me refresh let me remove that token so we're not cheating here so let me remove it from the local storage and let's try it out and let me refresh one more time we have no token okay that's awesome i can see not authorized to access this route so i can clearly see that my functionality works at least for now and then of course if i wanna see something i'm gonna go with anna and then i say secret and then we submit and user is created token is present so now of course let's get data and of course the user is still the same and everything is correct and if you want to try out setting up the user without any kind of values let's try it out we have please provide email and password and if we inspect we should see in the console bunch of errors meaning we have one for 401 and then we have one for bad request and again not to be redundant but all of this code refactoring and then introducing new packages as well as setting up more error classes is going to make way more sense as we progress to more complex projects my idea is following where i want to show you the simple setup first and then show you these changes on a small project because that way i believe that it's going to be easier for you to follow along because now we have only what six seven files something like that correct but as our projects grow we'll still rely on these topics we'll still rely on multiple error classes we'll rely on status codes as well as setting up the middleware but of course then it's going to make way more sense because we'll have way more routes and way more functionality and with all of this in place we're done with the project hopefully everyone enjoyed it and i hope to see you next one all right and welcome to our next project the jobs api where we'll finally combine our auth knowledge with crud functionality and as a result we'll have an api where users can log in and manage their job search during the project we'll also learn how to deploy our app to heroku so host our apps on the cloud and set up nice documentation with swagger ui for this project i still managed to build a matching front-end app but moving forward so in our future apps i'll exclusively use documentation to showcase the end result since building a front-end project for every api is just too time-consuming and before we take a look at the features let me stress one more time our job will be setting up the api so the back end the front end is there just to give you a better overall perspective on how the api is going to be consumed in real life and basically the idea is filing where we have some kind of front-end application and we can log in or register so of course if i haven't created my account then first i would need to register so i go over here and then i'll type some kind of gibberish i'll say that i'm peter the email will be peter gmail.com and then we go with secret now regardless whether you're logging in or registering will be sending the token the json web token and then on the front end will right away be able to showcase the user account so if i go here and if i say that i want to register and if i submit if i provide the correct values now i can see my dashboard since i just created my account i have no jobs so of course in here i just need to provide the values i'm going to go with apple again and i'm going to be looking for front and position i submit now i have my job i can delete the job i can edit the job and i can also take a look at the single job so in this page i'm actually fetching data about that one single job and i have functionality to edit once i change some values now when i'm sending this http request this is going to be a patch request so here i edit and if i provided the correct values then i successfully modified the job so now i can go back to the dashboard and i see that i have my job but in this case instead of pending which is going to be the default case we have the interview and if i'm no longer interested or maybe they sent me a rejection i can also remove the job and once i do that i have no jobs to display and as a quick side note if you're just interested in the front-end project just navigate to johnsmilk.com and at this point it is still on home page but if you don't see it there it's always going to be available in the projects page and you can quickly find it if you look for youtube now youtube doesn't mean that the project is going to be on youtube i'm just grouping my projects that way and then in here you can take a look at the application if you click on this massive master button and if you want to take a look at the source code just look for star files or complete both of them actually go to the same repo and then in the source you'll be able to find everything and a few things to know about the project when it comes to the url of course i'm using my api so if you want to clone the project and test it out on your backend you just need to change the url and that is in the ax usgs so in the source i have axios.js and as you can see the url is pointing to my backend but if you want to test it out on yours you just need to change the url and lastly keep in mind that i recorded this in july of 2021 so eventually once the react 18 is stable i might refactor the code to take advantage of the new features all right and as always we'll start with the setup and essentially we're looking for the folder number six of the jobs api and then more specifically we have two more directories we have the final one as well as the third and of course we'll do all of our work in star and then final is for your reference so this is the complete project now at this point you should be able to already spin up the final project if you want to just look for readme and then here you'll find the info where we do need to create a dot env file in a root and then set up two variables the uri as well as jwt secret one and of course this is gonna be the connection string the uri which you're getting from mongodb you just need to set up the proper password as well as database you want to use and as far as the jwt secret one for time being you can set up some kind of silly value like we did in a previous project because in the jobs one i'll show you where to get a proper jwt secret value and after that just run npm install and npm start and the final project should be good to go now as far as the starter we'll just navigate here to the folder and first thing that i want to do is go with cd and then drag and drop the star and before we do anything let's just go with npm install and npm start so that should install the dependencies and spin up the dev server and as far as the setup in this case we're going to have two controllers one for authentication and the second one for the jobs again we have db1 where we're connecting to the database that should be already familiar then we have errors folder with all our classes so we start with our custom api one and then we have one for bad request we have one for not found on authenticated as well as index.js where we essentially pull in all the classes and then we can start using them around the project since we have index.js we simply need to reference the errors folder and that will be the default export and then we have middleware one where we've got a authentication one so essentially this is going to be exactly the same like we did in the previous project however this one i want to retype from the scratch because we only did it once and then probably in the upcoming project we will reuse this one as well and then of course we have error handler one so this is where i got the custom api one and then i'm just checking if that is the case if that's our custom api we send the response with the status code as well as the error message and i'm using the status codes library and i prefer using this package because in my opinion it adds a bit more consistency to our application as well as it's easier to understand what's happening with a status code in this case we have internal server error and also during this project we'll do more work here in the error handler one because i want to show you how we can check for multiple mongoose errors instead of sending back always this 500 one with the long error message then we have not found so if the user is looking for the route that doesn't exist we send back 404 and then route does not exist after that we have two models so we'll have job and user and also the same goes for routes we'll have the auth as well as the jobs and then eventually we come to app.js where again we have two packages that we have used quite extensively dot env as well as the express async errors i don't think i need to repeat what they're doing then we're looking for express we invoke it and we set it equal to the app we have two middlewares we have not found one as well as the error handler one that we invoke dot json because there's going to be some post routes and we want to access data in reg.body there's a simple route app.get just a forward slash so this of course is going to be to our homepage just so we can test it out whether that's the postman or the browser and i pass in the not found one as well as the error handler one in app.use and i set up the port in this case i'm going to go with 3000 i believe the final one is 5000 and then we have a start function where we just invoke app.listen and eventually we'll add here more code if you can see clearly in console server is listening on port 3000 and if you navigate to the browser and go for localhost 3000 you can see the jobs api we are in good shape and we can start setting up our application all right and once our basic app is up and running let's start setting up the structure and we'll start with our controllers so essentially in here we want to set up the functions that eventually will be controllers for our routes and i want to start with auth and again this is just going to be a structure so we'll just add some dummy code like registered user or login user and that sort of stuff so let's go here with const register so this is going to be our first function and again it's going to be async rec and res and in the body like i said i'm just going to go to rest.send and we'll go the register user register user and then as far as the author out the second one will be a login one so let's just copy and paste and i simply want to change here the name for the function as well as the string so let's go with register login or i'm sorry we're going to go with login user my bad so login and let's go with user since i have the controller i also want to export it so we're going to go with module then export and i'll set it up as an object and we'll go to register and log in and essentially in order to speed it up i just want to take this whole thing copy and then back in the jobs we're gonna go with get all jobs get job create job update job and delete job essentially we have a crud functionality so i can just remove the second function as well as the login one we will rename them and let's just start with get all jobs so this is going to be a get route that gets me on the jobs so i'll say the same thing in string so get all jobs let's just change what function we're exporting and now we want to copy and paste this four times i believe one two three and four so we'll go here with get job this is going to be a route to get a single job then we have one for creating a job so create and job as far as the string we'll go with create job then we have one for updating the job update job and let's do it over here as well update job and lastly we have one for deleting job so let's say delete and job the same goes for the string so delete job and now i just want to add the rest of the functions in my object the one that i'm exporting so go with get job then we're looking for create job the update job so comma update job and delete job and once we have the basic controller structure in place now of course we can do the same thing with our routes and as far as our routes let's start with auth js and of course we need to set up the router so let's go with const express easy equal to acquire acquire and of course i'm looking for express remember we need to go with some kind of variable and micros router and we'll set it equal to your express dot and router we invoke it and then we'll import both of the functions from auth controller and remember the names were register and login so let's go over here login and register and both of these things are coming from our controller the auth one so let's navigate over there we have controllers and of course the auth one and once i have my imports in place now of course we just need to set up the routes and if you remember we also had an option of router and then that and then whatever is the method and both of these are going to be the post routes so i'll simply go with router that post and then we go with forward slash register and then of course we'll pass in our controller after that we'll copy and paste again router.post in this case we're looking for the login one and of course the controller will invoke he is also going to be a login one and then at the very very end we'll just go with module exports and that is equal to the router so that should do it for auth.js and before we navigate to app.js and import it and set it up let's also do the same thing with the jobs router because essentially the idea is exactly the same where i want to go to jobs and again in order to speed it up let's just take these two lines of code and i'm sorry i navigated to the wrong file so here in the jobs i set up the router yep that stays the same and now we just want to go with const and we want import we want to import get all jobs get job also i'm going to be looking for create job create job then we want to update the job and lastly we want to get a job or i'm sorry not get job delete job delete and job and all of that is coming again from the controllers correct so go with require and we'll set it equal to the controllers folder and of course we're looking for the jobs and once we have these imports in place now of course we'll do the other way where we go with router dot route and then we'll have post and get on a forward slash and then we'll have the get delete and patch on forward slash and then the route param so let's go with router dot route and this is going to be the forward slash of course and therefore we'll go with post so this is going to be to add the job and get all the jobs remember that was the structure for rest api and we're looking for the controller of create job of course let's go with dot and then get and this is going to get me all the jobs then we'll copy and paste and i'll add here the id remember the route params and in this case we're not going to have post so i can remove this one and we'll start with get now this is going to get me the single job here then we're gonna have one for delete of course the controller is delete job and then lastly we have one for patch and here we'll pass in update job and then at the very very end of course i want to go with module dot exports and the router now of course if you prefer this index you can also use it here in auth js i just thought that this is a nice refresher where of course we can set up our routes this way as well and once we have both of the route files in place now of course we just need to go to app.js we need to import both of them and again as always this is really up to you but i'm gonna do that above the error handlers because there's also going to be a connectdb here so connect db is still coming up let's just go with routers and here let's say const auth router and that of course is equal to require and we're looking in the routes and then more specifically of course i want to access the auth one copy and paste and this is going to be a jobs router of course this is coming from routes and forward slash and jobs and then i don't think we need a dummy one anymore i think we are pretty clear on what's happening so now of course let's remove it let's say app.use and as far as the path i'm going to go with api version 1 again that's my setup in postmatch so we might as well continue using that one and as far as the auth i'm going to go with forward slash auth and of course what that means in here we have the full path of api version one auth and then register and the same goes for the login and as far as the jobs will do exactly the same we'll go with api version jobs and then the forward slash is just going to have the create one and get all of them and then the route params will have the rest of the three hopefully that is clear because again we pretty much keep repeating the same thing so let's go with api version one and then auth and then let's just pass in the auth router so now of course we just need to copy and paste and let's go with jobs1 and of course now we want to implement the jobs router so i'll say over here and i don't think i'm going to do any kind of testing since it doesn't make sense at the moment i'm just going to check my error so it says over here router.post requires a callback function but it's not given so let's see let's see let's see maybe i didn't export something so let's go to jobs that's the router and of course i'm looking here for the auth one for some reason so let's remove this one and then as far as create job looks like i didn't export it or something along those lines so let me take a look at the jobs of course there's a naming issue it's a create job so create job and of course i need to do it over here as well so once i fix this tiny bug now we should be heading in the right direction where we have the routes we have the controllers so now of course we just need to start adding the logic and the reason why i'm not testing anything right now because of course we'll work in each of the controllers quite extensively and before we do anything of course we'll just check whether we're getting this silly string response and if we do then of course we'll work on our logic all right and before we can start registering our users the last thing that we need to do as far as the general setup is to set up connection to the database and of course we have the function we already have connect js we have the functionality where of course we use the mongoose we set up to connect we pass e in the url and of course these are going to be our options to remove those depreciation warnings and the only thing we need to do is set up in a star dot env and here let's go with underscore uri and of course you want to pass in your connection string so let's go to connect we're looking for connect your application i'll take this one over here and copy and paste and as far as database i mean it's not going to be a surprise if i go over here with 0 6 and i'll call this jobs api and then of course i just need to provide my password and once you do that just navigate to app.js so let me close everything just so it's not so busy and i guess in the app js i'm going to go above the routers i'll say const connect and then db and that will be equal to require of course and we're looking for our function and that is located in the db folder not the error sorry the db one and now we're looking for connect and then we'll just scroll down where we have the start and we'll go with await and we'll invoke the connectdb and now of course we want to go process dot env and then the underscore and uri so underscore and uri and once i save and if i can still see servers listening on port 3000 that means that our connection is ready to go and now can finally start setting up our authentication all right and once the database connection is in place the first thing we want to do is to create a user model and in a process we'll learn a few more built in mongoose validators and as xenon if you need to reference the steps we're about to take just navigate to the readme in the root so in the star route look for readme and here you'll find all the steps and since i want to show you more validators let me open up the mongoose docs so in here we're looking for a validation and then more specifically just look for the string one because in the user pretty much all of them are going to be strings so just click on any of these ones and here and there i'll just use this as a reference just to showcase what's happening and essentially we want to navigate of course to the user model so the file is over here and remember we're looking for the is of course so const mongos is equal to require and of course i'm looking for the mongoose and after that we will add two more packages the jwt one the json web token one as well as bcrib js but of course that is still coming up and i want to start by creating a schema so let's go here let's call this user schema not as equal to new mongoose and of course we're looking for the schema here in this case and i want to go with parentheses pass in the object and as far as the properties will have three we'll have name email as well as the password so let's go over here with the name that's going to be the first one i think i can close the sidebar just so i have a little bit more real estate and we'll start with type type will be equal to string then we'll right away set it equal to required and then we'll set it equal to array remember the first value is whether it is true or false of course in my case i'm going with true and then we'll say please provide a name so of course that is our required validator and after that i just want to showcase that in the mongoose docs we can see that we have min length and max length now of course as far as the values that's really up to you my case i'm going to go with min length and i'll set it equal to 3 and of course i'm going to also set up a max length and i'm just going to say 50. then i want to go with email and in order to speed this up we will copy and paste and of course i'll change the name here this is going to be an email then i'll still set it as required so that's going to stay the same let's set it over here and then we also have a match one which pretty much creates a validator that checks if the value matches the given regular expression now why we want to use that because i want to use the regular expression to check for the valid email there's plenty of suggestions out there most likely the first answers that are going to pop up are going to be from stack overflow just pick the one that makes the most sense to you and you'll be good to go now as far as this project you have two options you can either get the code in the readme or just look in the final one so in the final of course i have the models and all that and then just look for the user one and you can take the entire property that's really up to you so in my case i'm just gonna navigate to the readme i'll take here this code and then i want to go back to the user and more specifically the email i want to remove both of these the min length and max length and then we want to go with match and we pass in the array so essentially that's the syntax and then we want to pass in the regular expression then comma and then whatever error message we want to provide and in this case it's pretty much going to be the same i'm just going to say please provide valid email and once i have the match in place the last thing i want to set up for the email is unique and true and essentially what unique does it creates a unique index and this is something you need to be aware of where technically it's not a validator and that becomes important when we run validate method manually which we haven't done so don't lose your sleep over that and when you're writing automated tests and of course you can read more about it in the docs but the way it works it just creates that unique index so if i'm trying to save a user but there is already a email news then i'll get the duplicate error message and lastly i want to go with password and here i think i'm going to take the name because pretty much is going to be exactly the same where i'm going to go with password password and then required will be true now of course the error message is going to be a little bit different say here password and then as far as the middle length and max length i think i'm going to go with 6 and no longer than 12. so let's set it up this way we have the user in place the only thing left to do is of course export it so let's go with module and export and i'll set it equal to our mongoose model and of course we want to pass in our name and my case i'm going to go with user as well as the user schema so user and schema and once we save now of course we can start setting up our register controller beautiful our user model is in place so now of course let's set up the first route and steps are going to be following where first we want to validate a name email and password whether of course the user has provided the correct values and in this case i'll purposely go with mongo's option just because i want to show you how we can send back nice error responses instead of those big objects then we want to hash the password and don't worry if this looks like gibberish to you right now of course i'll cover it extensively a little bit later after that if we're successful if we can hash the password if the values have been provided then of course we create the user and once we have the user we want to create that token that's going to be associated with that user and with that token the user can start creating resources which of course in our case is going to be jobs and in order to get that token to the user of course we will include it in our response so let's get cracking and of course we're looking for the controllers in this case and of course i have the final open so i'm actually in a wrong folder so let me look for controllers we're looking for the auth and of course more specifically the register one we can start by importing the model so in here i'm going to set up a user and that is going to be equal to require then we're looking two levels up and of course i'm looking for the models and then more specifically a user model and once i have the model before we do anything here let's just check in the postman whether we're getting this silly string because if we don't then of course we do need to troubleshoot so let me navigate back of course here i have all my workspaces and i'll create a new one that's not a surprise i will rename it and i'll say 0 6 and let's call this jobs api now the url of course is going to stay the same remember that global variable so that saves us a little bit of time and i want to go with new request this is going to be a post request and here i'm going to be looking for my url of course so url and then remember we're looking for auth and register hopefully that is correct let me just double check so in the here i have api version one so that should be still in my global variable in the postman and then more specifically auth and then if we take a look at the routes in here in the auth of course i have the register and like i said both of them are going to be post routes so why don't we start by selecting a body then we're going for raw we want to go with json and then let's just set up the name and it's not going to be surprised if i'm going to go with john then as far as the email let's just go with the dummy one so i'm going to say john gmail.com and then lastly we want to go with password and i'm just going to stick with secret because that's the most simplest one in my opinion so i have name email as well as the password and of course once i send i should get register user if you don't then again please troubleshoot because otherwise anything we're about to do it's not going to make sense and before we move along let me just save this one and i'm going to look for my jobs and let's just call this register and user so let's save it over here and let's right away test whether we're getting back the correct values meaning whether i can access them in a reg dot body so change this one around where we'll say res.json and i'm just going to pass in reg.body again in this case i'm just checking whether my middleware is correct and if i can see all the three values that i'm sending from my postman then of course we are in good shape now i also want to get these status codes remember that was the library that we used before so let's go over here let's say const and we're looking for status codes and that is coming from our library the http status code so require require and we're looking for the http status codes and then in here i want to set up the status status and of course dot json after that and let's just go with status codes and then we'll set it up as created because remember we are creating a resource so this will send back the 201 and once we have all of this in place now of course we can create that new user correct so let's go here let's say const user and we'll go with a weight because of course this is asynchronous then the model name user and we'll go with create method and in the create method since i want mangoes to do all the validation i'll simply pass in rec.body just like we're doing over here so now of course i can remove it from my json and for them being i'll just send back the user our current code actually is a big big mesh because we're saving the passwords as they come in as strings and that's a very very bad practice and don't worry we will fix that a little bit later for now i just want to see whether everything works and once we hop back to the postman we should be able to send a request and in my response i can see that i created a new resource in a database since i have that underscore id and then the rest of the properties that i provided in my request and with this in place now of course we can move on to our next step beautiful we can save our user and before we cover why it's such a bad practice to save our password as a string now let me remind you about the error checking and more specifically let me just jog your memory on the fact that we can check for the empty values right in the controller because keep in mind that at the moment we are doing that using the mongoose so first let me show you how we can do that in the controller and then i'll talk about it while we're checking in the mongoose essentially what i'm trying to accomplish and if you remember we simply check it in the following way where we go with name email and password now all of that is coming from rec that body of course and then we want to go with if and if one of the values is missing then we'll throw our own custom error more specifically the bad request one so let's say over here email and then we'll do the same thing for the password so if one of them is missing then of course we'll throw the error and of course we need to import that so say here const and we're looking for bad request quest and error so that's the one we're looking for now if you don't want to make the typo then of course just navigate to the errors folder more specifically index.js and then just grab this value so that way you'll avoid some unnecessary typos so let me just make sure that the name is correct looks about right and then we want to go with require of course we're going two levels up and we're looking for the errors and since we have index js over there of course we don't need to be more specific by default we'll get back the index.js and once i have the import in place now of course we just want to throw the error in the if block where it'll say throw new and of course i'm looking for bad request one and then we just need to pass in the message because remember the status quo is already there and let's just say please please provide name email and password and password and once i save and once we navigate back to the postman if i'll remove the password completely and if i'll just send notice now of course i will get the message now our functionality will still work because of course we're using the mangos validators even if i remove this code so if i comment this one out and if we go back and if we send without a password or without any of these two values as well of course we'll get back there now the reason why i'm using the mongoose validator because during this project i also want to show you how we can send back more meaningful response because at the moment of course i'm sending 500 which technically isn't the case because of course now we have a bad request instead of internal server error and also notice these massive objects probably would be better if we would send just please provide the password or the email or the name and therefore in this project we will use mongoose validators quite a bit just because of course i want to show you how we can send back more meaningful messages but that doesn't mean that we're not going to check in the controller so of course this one is optional but there's going to be some cases where yes we will have to set up that check directly in the controller so this one i'll remove because this pretty much is a repetition here but when it comes to different routes yes there might be some cases where we check directly in the controller hopefully that is clear so now we can start tackling the password issue not bad not bad if we take a look at our database we should see user's collection and overall life is great if only not for one big doozy notice how we store password as string so now if someone breaks into my database he or she can easily ruin the life for all my users since in most cases people use the same password for everything so if there's one thing i want you to take away from this course please never ever store user passwords as strings trust me they will thank you for that later okay well what's the solution well we want to hash them instead which in simple terms means generating random bytes and combining it with the password before we pipe it through the hash function a mathematical algorithm that maps data of any size to a bit string of fixed size something to remember hashing is a one-way street meaning it cannot be reversed also if the input changes even tiny bit the resulting hash will be completely different which is really really good for storing passwords since we can accomplish two things at once store passwords in a form that protects them even if the password itself is compromised and at the same time being able to verify the correct user password both of which will cover extensively in the upcoming lessons when it comes to password hashing for this and following projects we'll use a library by the name of bcrypt.js again the library is called bcrypt.js and if you're using a star i already installed it for you so we can start using it right away and as far as the syntax for hashing the password it goes something like this where first we want to import the library of course and we're looking for the bcrib js again please keep in mind that the library name is bcrypt.js don't install the beaker one and then wonder why you have bugs so again the name of the library is be crypt.js and the only reason why i'm telling you that because i fully understand that it's very easy to mix them up and once we have access to the library instead of dumping the entire body with our name email and password we want to create a new temporary user object and in here i'll just pull out the values from direct that body so my apologies we already had this code but i removed it with a bad request so now i'll have to retype it one more time so we'll look for name email and password and all of that is coming from rec.body and then i want to set up the temp user object and of course keep in mind that in the temp user all three properties need to be there otherwise we'll get back the error so of course in here i'm passing reg.body now i want to set up a new object and you'll see why i'm telling you that in a second and effectively i first want to set up the hashed password and then i'll go over line by line and explain what's happening so let's start over here with const temp user and we'll use the es6 thing where i'll go with name is equal to name and emails equal to email and what i want to do here is set up also a password but password will be equal to a hash password which of course at the moment we don't have and in order to set up the hashed password we need to run two methods we need to run gensalt and then the actual hash method and first i want to create a variable and i'll say salt and we have an option of running them asynchronously so just go with a weight then i'm looking for bcrypt and like i said the method name is jen salt and then we want to pass e in the number value again i'll explain all of this in great detail in a second and then once we have the salt then we want to create that hashed password so let's say over here hashed and password and we'll go with await then bcrypt again decrypt and the method name in this case is hash and we need to pass in two things we want to pass in the password we want to hash as well as the random bytes which essentially is that sold so let's start over here with password then comma then we pass in the salt and now where we have the password in the temp user instead of directly using the password we'll go with hash password and now of course instead of dumping the entire body we'll go with dot dot again we want to spread them out and then we'll go with temp user and once we save all of this now let's hop over to the postman and let's try to send the request so in here we need to keep in mind two things first the fact that we have set up four unique emails so if we'll try to send the same email we'll get the a response that's number one number two remember when we're setting up the password the basic password we also add the max length since i wanted to showcase that we have that valve there now in this case of course we will get an error because the hashed value is going to be way longer than 12. so let's try it out let's send and like i said we will get an error where the max length is 12 and of course this is the hashed password value and in order to fix that of course we just need to go to our user model and then remove the max length like i said i added this just so you can see that we have this option but of course in our case we are not going to use it and then once i fix that then the another bug is going to be that we have a unique email so if i send with john gmail.com of course i'm going to get an error which pretty much tells me that i have error and more specifically there's an issue with an email and this is the case where again we'll work on these custom error messages in a second now we simply want to change the john to john 1 at gmail.com and once i send check it out now of course i'm getting back the user now it's still not a good idea to send back the password so that's also something that i will work on a little bit later now the good news is that if we navigate right now to our mongodb and if we take a look we'll see our second user with a email of john 1 and of course now the password is hashed and what that means is that even if someone breaks into our database and steals all the data instead of actual password values they'll get the hashed ones which prevents them from easily reusing them later now that doesn't mean that you shouldn't protect your database of course not that's not what i'm saying just make sure that you always always hash your passwords and never ever ever store them as strings and as far as the code if we take a look at auth.js in line 9 we generate salt which essentially just means random bytes and we do that by running the method gen salt and in there we provide a number of rounds so how many random bytes we'll get and of course the bigger the number the more random bytes we'll get and of course that also means that the more secure our password is going to be but we also need to keep in mind the more rounds you have the more processing power is going to require and therefore i just went with 10 which i believe is a default one and trust me that is already a very very secure password and then of course we take that salt so there's random bytes and we pass in the hash method and hash method is simply looking for the password so the password we want to hash as well as the result and once we provide both those values as a result we get back that hashed password and of course that one we can safely store in our database so we just add it to our user and we're good to go beautiful we now know how to hash user passwords and if we take a look at our register user steps essentially we just need to generate a token which should sound already familiar since we spent the entire project on that and we'll be good to go right well yes and no that's true we don't have much left but if we take a look at our controller it's getting somewhat busy so if we'll keep on adding more functionality and just keep jamming the code in the controller eventually it's going to get bloated and way harder to manage now what's the solution you might ask well another set of middleware only in this case we're talking about the mongoose middleware but just keep one thing in mind the end result is going to be exactly the same will still hash users passwords it's just the logic will be stored nicely in a separate place and since i want to show you the entire documentation i'm going to navigate back we're looking for the middleware and of course you can read yada yada yada we have pre and post so before and after hooks and essentially we're looking for pre and more specifically pre save and the way we set it up we have the schema so in our case of course that is going to be our user schema then we go with pre so that's the syntax and we're looking for save so before we save the document and then in the callback function this is where we can access the properties in a document and do some exciting stuff and of course since this is a middleware then we just go with next and once we're done we pass it on to the next middleware now i'll also show you with async weight so this is coming up first let's just focus on this next one over here and essentially what we want to do is take the bcrypt we'll just save a little bit of time and we will go to our models we're looking for user one of course and then here let's copy and paste we have the bcrypt let's keep on scrolling okay that's our setup and here this is where we want to go with our schema so before we set up the model we'll go with user schema that's the name of course then we're looking for pre and then save so pre-save and since we'll use a weight we'll right away set it up as a sync and then let's go with function and i highly highly highly suggest using the good old function keyword value because that way this will be scoped to our document so if you'll go with arrow functions if you're familiar with them you know that as far as scoping this there's different set of rules in this case if we use the good old function that's why you'll see that in the docs as well this will always point to our document so in here let's go with our function and it is a sync nice then let's pass in the next of course and then remember the functionality what are we looking for over here well i want to generate the salt correct and of course i want to get the password and just so we get comfortable let's write it from the scratch so let's go to the user one and essentially i want to go with const salt so now we're generating those random bytes so let's just go over here with a weight and then be crypt and of course the function name was gen salt and i'm not going to go 20 rounds i'm going to go with 10 here and then as far as the password well this is where the callback function comes into play where in this function this will point to the document so when we type this over here basically what we're talking about is our document before i want to save the document what do we want to accomplish well we want to hash the password correct so what we can do we can go with this dot and we're looking for password so of course this is over here and we simply want to go with await and we want to hash it we want to go with await then bcrypt and then of course the method name is hash and then we're looking for this.password so our current password for saving and then we pass in salt and that's it that's all we have to do and once we're done with the functionality what's left well we want to pass it on to the next middleware so we just go with next and we invoke it and now check it out if we take a look at our controller since we're not sending the bad request here anyway i don't really need all these lines of code that's it i simply want to take my body just like we had before with dot dot erect.body and everything else is taken care of over here and you have to agree that this is much cleaner and nicer to work with so let's go back and then like i said i'm not interested in any of these things over here and we'll simply go with dot dot correct that body i'm still sending the user just because i want to showcase that will be hashing the password but don't worry that's also not a good practice to send back the password so we won't do that in a few seconds so let's go back to our postman we want to send it and check it out we have john with john blah blah blah and of course we have our hashed value so our functionality still works and the last thing that i want to cover in this video notice the docs in mongoose 5.0 blah blah blah next we can go with async await well that simply means that back in our user one can just remove it and what they're telling us in the docs that it's still going to work so let's test it out in this case i'm going to go with john 2 since remember we have those unique emails let's send it and we still get the response so we know that that works and if i go to my database now of course i should have quite a few users already there with hash passwords apart from the first one of course that is where the secret is and now i can remove it and we are good to go now we can hash the password but we're doing that using the mongoose middleware nice we're a little bit familiar with mongoose middleware so now let's continue with our steps we're saving the user so we're good on that and now of course we just want to generate the token and send back the response and we'll first set up functionality again in the controller so we're clear on what's happening and next video i'll show you another nifty setup that we can use with mongoose and like i already previously mentioned this should feel familiar because we spent the entire project on that the jwt basics so if we go back to the controllers in the fifth project meaning the folder name is five of course this is not the fifth project and if we take a look at the main check it out we go with jwt sign correct and of course that is coming from our library the json web token one then we pass in whatever we want to pass it on to the front end and of course later we'll use the id to access the resources that are associated with that user then we pass in the jw secret one and in this project i'll show you where we can get a proper value and eventually we pass in the options and we just say in how long it expires so let's try to recreate that back in the auth.js and what are we looking for here we're looking for the library of course now i can remove the bcrypt because everything is already set up in model so let's go over here with jwt we will set it equal to require of course and then we're looking for the package the json web token one and then once we create the user this is the case where we want to create that token correct so let's go over here with const and then we'll go with token and for time being i'll just pass in some random string and then we'll set up properly everything after that so let's go here with jwt then we go with sine of course and we want to pass in the data we want to send back and in my case again we'll go with id and name so let's start with user id that's just how i decided to call my property here so user id is equal to user so that's the user that i'm getting back over here and remember on that object we have id property correct and if you want to double check it's right over here this is what we're currently sending back and we go with underscore of course and then we'll go with id and again that's just my preference to kind of separate the two otherwise you have job id you have user id and many more ids and then if you just keep using this underscore in my opinion is just harder to manage everything so that's why i always go with user id job id or whatever so that's the first thing that i'm sending and next i want to send the name so i go with name and then again user that's my object and the name and like i said i'm just going to pass in some jwt secret right away so i'm just going to be cheating a little bit over here and then we'll add a comma and then let's go again with expression remember this one was expires in 30 days so use the same value and of course a little bit later i'll talk about other options as well so let's go here let's say expires and in and i'll set it equal to 30 days then we save and of course instead of sending back the user i want to send back the token and this is the case where as always there's multiple setups that you can have you can send back maybe only the token or you can be like hey maybe my front end needs the name directly now what am i talking about if i go back to the application that i built for this project if i go to login and of course more specifically i'm going to be looking for register and then i'll try to use some kind of values here that are not already a database so i'm going to go with anna and maybe let's add a tube because then for sure everything is going to work once i submit not only i'm going to get back token i'm going to say here never i'll also get back the name but again this really depends on the setup that you have on a front end you can send back only the token and actually there are setups where the front end decodes the token instead instead of me sending here a name and set it equal to username front end decodes the token now it's not going to be our case but just keep in mind that's why you don't ever want to store anything here as far as the secrets because as far as the coding you can actually do that now of course when it comes to verifying that's where you need that jwt secret but as far as decoding yes there are some setups where front-end just decodes and gets whatever property it needs so in my case the jobs app i'm also looking for the user and more specifically the name property but hopefully it is clear that in this case it's just my preference when i was building the front-end app when it comes to response what you definitely want to send back is the token because that of course will allow that user to access resources on the server later on so my guess i'm going to go with user so that's going to be another property i'm sending and in this case of course i'll access my user object and i'm just going to be looking for a name so i'll have another property there by the name of name and then i'll set it equal to user and then name and of course now i just need to add a comma and we're successfully sending the token and again let's test it out in a postman first so i'm gonna go here with john3 at gmail.com we send it back now notice we're not sending back the password anymore and of course i'm getting the user as well as the token and just to reiterate on the front end of course i'm using the ana over here so in react i set the state and i set up the state value just to showcase that notice over here i have my reducer blah blah blah i have user and notice the name of course that is anna and i'm accessing that right from the response and then when it comes to the token you'll have multiple options and one of them is going to be storing it in a local storage so now of course in the local storage not only i have the name so that way when i refresh of course i can still showcase data but i also get the token so when i'll be making future requests on behalf of anna of course i'll have the token hopefully it is clear and now of course we can take a look at another solution that mongoose provides to make our code cleaner awesome and to complete our register functionality let's learn about schema instance methods in mongos so i'm going to navigate to the docs in this case we're looking for schemas and if we take a look at the list we see this instance method and essentially what happens every document we create we can have functions on them so these are going to be instances of course of our schema correct and the way we set up those functions we go with the schema name then methods and then whatever function you want so essentially once i create that user over here in the register that user will have a function and you can probably already guess that we'll create a function that just generates that token and of course in that function we'll pretty much have the same code and therefore we won't have to bother with that in the actual controller in the register controller and let's start somewhat silly where i want to go back to my model the user one and let's just go with user schema so of course that is the name that stays the same then we go with methods and then let's just say get name so let's imagine that we're just lazy getting the username and we have multiple options we can set it up as async or we can just set it up as a regular function so in this case we'll just go with a regular function so no async keyword but again we do want to use this function keyword not a our function because that way this will always point to our document and with get name simply what do i want to do i want to return this dot and name and now of course we just want to go back to auth.js and where we have user.name let's just invoke let's say user and we're going to be looking for get name so invoke this one and now let's go to the postman and let's try to send it so i'll navigate back i'll send it and because i wasn't careful of course i didn't pay attention to my email so of course i need to change it to john4gmail.com and i can clearly see that i still have the name so if i'll change this one around then if i'll say anna and maybe i'll go with anna gmail.com then i'll still be able to access the name and what that means is that we can generate the token using the instance method instead so again we're trying to keep all our logic in one place where we have the user schema instead of scattered around our controllers and let's just fix everything back we'll say username we'll stay with that for time being of course we can cut it out and i think we'll retype one more time from scratch just so we can get comfortable with jwt now i'm not gonna need the import here for the token anymore so i can definitely cut it out i have my user awesome and eventually i'll invoke a method that will get me that token so now let me save auth.js back in the user of course the name is not going to be get name and you know what i'll just set up everything from scratch i'll say user schema then again the syntax is methods and then we're looking for the function name and in this case i'll call this create jwt and again it's going to be a simple function here and as far as the logic we'll just return right away jwt sign and of course in here i need to get the library so let's go with jwt at the top and then jwtc sign and again remember in the function we can access the document how well by using this correct and as far as the payload again i'm going to go with user id then i'll set it equal to this and underscore id so this points to the document and then we're going to go with comma name and then we'll just go with this dot name and again we'll just cheat a little bit where i'll say jwt secret and then as far as the expression again we'll keep it at 30 days so expires and we'll set it equal to 30 days so now if i go back to auth.js i simply want to call create jwt that's it that's all we have to do so once we create the user of course we have that instance method and here i can just say token and i'm going to go user and of course the name of the method is create and jwt we invoke it and now of course we can go back to our postman now we already have one anna and let's just change the name just so we can see that it works we'll go maybe with peter and i'll set it here as peter as well and then once we send of course now i have the peter as well as the token and of course that means that everything works and successfully we're done with our register controller and in the process we learned about hashing the passwords setting up the mongoose middleware as well as the instance methods on a schema all right and once we're good with register route like promised let's swing back to the json web tokens and the first thing i want to talk about is the expression so remember in options we go with expires in and as far as default setup so if we just provide a number this is going to be in seconds now if we provide a string then we need to make sure that we add time units whether that's days hours and all that otherwise it's going to be interpreted as milliseconds so if you go something like this string of 120 it's going to be equal to 120 milliseconds and of course we'll return to this one once we start refreshing the tokens and all that cool stuff for now just be aware that by default it's going to be seconds unless you provide a string with a time unit that should do it for expires in and as far as that secret string yeah you can get away with jw secret but of course a more proper setup is generating some kind of more secure key and i prefer using all keys generator dot com again this is a free one of course if you want you can donate and all that but you can use it for free you're looking for encryption key and then more specifically you're looking for 256 bit one and then of course you can get the value and just take that value and stick it in the dot env file and as a side note we can also set the expires in ind ind.env as well and actually this is exactly what we'll do right now so let's navigate back to our project i'm looking for dot envy and then i want to set up two values i want to go with jwt underscore secret and that is going to be of course equal to my encrypted one and then the second thing that i want is that expiration and as far as the name i think i'm going to go with jwt jwt underscore and lifetime and now of course once i have both of these things and as i know of course i need to set it to some kind of value so in my case i'm going to go back to my 30 days and once i save both of them now of course i just need to spin up the server and i'll be able to access that in my user model and once my server is up and running i can just go back over here and instead of hard coding simply go with process dot env and in this case of course i'm looking for jwt underscore secret and then as far as expires in i'm gonna go with my value and again we're looking for process dot env and we're looking for jwt and lifetime or however you called your variable and once we have both of these in place now of course let's test it out just to make sure that we don't have any silly bugs and let's go with peter and we'll set it up as 23. i send and everything is correct so once i have all of this in place now of course we can switch gears and set up the login functionality beautiful once we can successfully register the user now of course let's worry about the login functionality and honestly we have covered pretty much all of the things apart from checking the password so of course since we're using a library to hash the password of course we want to compare it as well now since that involves creating another instance method we'll actually do that in next video in this video simply want to check whether we're getting the email and the password with some kind of values because that's the whole setup for the logging in in this case they don't need to provide name they just need to provide email and a password if they don't we send back the bad request one after that we'll check for the user in our database so basically we'll go with our user and find one and we'll pass in the email and if we can find one then of course we'll send back the user and if not then of course we'll send back another error and let's start here by removing that not send i'll close the sidebar here and let's start by const email and password and this is the case where i'll do the checking the initial checking right in the controller and i'll actually cover why that's my preference in this case once we're done setting up compare passwords functionality so first in the request i'm looking for email and password and right out of the gate i'll say if no email or if no password then of course we'll go with our bad request and of course we'll do that in if block and we'll say throw new and we already have the import for battlequest so we just go with bad request error and we just need to provide a message please provide email and password and once i have this one in place then of course we want to check for the user correct how do we check for user well we have the model we have the user model and on it we have a method by the name of find one so let's come up with some kind of variable name and microsoft's going to be user and we'll go with await of course it is asynchronous then we go with user dot and find one and then instead of passing in the id and all that we'll pass in the email so whatever we're getting from the user we'll just pass it in here and effectively at this point we have two options if the user exists awesome then of course we can send back the response with the username as well as we can create token of course now if the user doesn't exist then of course we want to throw another error now in this case though we're not going to be throwing bad request error in this case if there is no user then of course we'll send back the unauthenticated error because in this case the user is not providing valid credentials and that's a big difference so let's go back to auth.js of course we want to import that so in here let's go with on authenticated error that's the class we're looking for and in here let's check and eventually there's also going to be code for comparing the password but like i said we'll do that in next video so that is still coming up for now we'll just say if there is no user then please throw that error throw new and again we're looking for our auth error and we'll simply say invalid credentials credentials and once we have taken care of this now of course we want to create the token because if we go past this error that means that user is there user exists and remember the instance method we created in the previous videos the create token one or create jwt don't remember i believe it was create jwt of course we want to invoke it and essentially we want to send back the same response so the same response as we sent when we registered the user so if user exists let's create that token and of course we'll go with user create jwt we invoke it we get back to token and now it's the same deal we go with status now in this case we want to go with status codes and it's not going to be 201 it's going to be 200 and of course that one is the okay one and then as far as the json same deal also in my setup on my front end i'm looking for the name property so not to be redundant but you always want to send back the token but optionally you want to include some more things as well and in my case those more things is just a username so go with user for name of course the property and then username and then comma and of course in here we're looking for a token so right after the name we'll go token and of course that is equal to the token that we're getting back from create token and now of course we can go and check it out in the postman so let's go back over here i believe we just created peter 23 so now let's just test it out i'll create a new route so let's say here new route it's still going to be a post route of course and as far as the url again we're looking for our global variable forward slash and it's going to be auth and of course in this case it's a login one and then let's just grab these values over here let's say that we'll take the name email as well as the password and of course we won't use the name but we can nicely copy and paste just to save a little bit of time copy and paste and of course forgot about my curlies so let's place it here properly everything and this is turning out to be a mess okay i set up everything correctly over here and i don't need the name and i'm just going to be sending the peter 23 with a secret again for time being we're really just checking whether that secret is there i'll save it and i'll say in the jobs one and we'll say login user and then let's test it out cursor here still have the body yes everything is correct and of course i'm getting back to peter now if i'll do some mistakes if for example i'll remove the password we should get the 400 one and that's the please provide email and password okay that's good let me add the password and now let's mess up the email instead of 23 i'll go to and now of course i have invalid credentials and of course the error in this case is 401 so our base functionality works really great the only thing that's left to do in here is just to compare the password using our library and if you remember the library name was bcrypt js not bad not bad we can register user we can almost log in and the reason why i say almost because of course the moment as long as there's some kind of value for the password we're actually sending back the token so now let's fix that let's actually compare the password and this is that interesting thing where you might be like okay but wait a minute back when we were registering of course we were hashing this password correct we went with gensalt and then hash and the deal is following where essentially we have our library we have the package dbcrypt1 and in the beaker package of course there is a function by the name of compare and it compares the hashed passwords so again it's a one-way street once we hash the password that's it but with compare method we compare those hash passwords and of course if they match awesome we send back the token and user has successfully logged in and of course keep in mind that we can set up this functionality right over here but why we would want to do that if we already know how to set up the instance methods so instead of jamming more code in the login controller we'll simply go over here and i'll say user schema and of course we need to go with methods and then as far as the name i'm going to go with check password or compare password again naming is really up to you in my case i'm gonna go maybe with compare password sounds a little bit more sophisticated and this is going to be a sync function and then this function is going to be looking for one argument and that of course is going to be the password that's coming with a request and i'm just going to name this one candidate password and password and then as far as the function body i want to come up with some kind of variable and in my case i will call this is match and we'll set it equal to a weight because we can run the compare method asynchronously and we'll say await again the package name is bcrypt of course and then the method name is compare and then in the compare we'll pass in two things we'll pass in the password so the candidate password essentially the password that is coming in with a request and after the comma of course we'll get the password from the document of course the one that is already saved in a database so let's go back to the compare and we'll just go with candidate password so again the one that's coming in with the request and of course in order to access the document password we simply go to this dot and we provide the password and then what we want to return from the function is the match so let's say here returned and is match and once we have the function in place now we simply want to go back to auth.js and if we can see that we have the user we also want to set up one more if statement where we'll check the password so now of course i can move this comment down and i can say if there is a user i also want to check whether the password matches and we can do that by going with const and then come up with some kind of variable is password correct and of course we need to go with a weight because our function is asynchronous then we're looking for the user so of course this only happens if we have a user if we don't have the user then we right away send back invalid credentials and here we'll go with check or i'm sorry compare password of course i went with sophisticated name then we pass in the password that we're getting from the user and now of course we want to do the same thing where we want to check if the password is correct then of course we just return a token and all that if not then we'll throw the error and i'll just speed this up and we'll copy and paste and we'll do the same thing if the password is false meaning if we get back is match as false then of course we'll just throw this error and now let's go and test it out in the postman so at this point i have email as well as the password and they should be correct so let's send it here and of course i get back the response but if i start messing with the values for example if i go with a wrong email now of course i'll get invalid credentials so let's set it back to 23 and then if we do the same thing with the password we'll also get back the same message so notice here we have this invalid credentials now if i provide the correct values the correct email as well as the password then of course everything is great and we get back the token now lastly you're probably wondering okay but why did you check over here right in the controller because technically we need to understand that yes if there is no email of course we'll get that mongo's error correct well let me showcase something so i'll comment this one out so basically now we're not checking for empty values and let me provide the correct one let me say that yeah the correct email is going to be peter 23 yay area but i'll remove the password and essentially once i send i get back this error response but it is empty so let's go over the reasons why is that happening well if we take a look at the user of course we have the compare one and this one will throw an error it will throw an error because of course we're passing in the empty value correct back in auth.js we're getting back the password but password is just empty string and we are getting the error and we are actually handling that error in our error middleware so let's go back over here the error handler we are handling it over here and i can actually showcase that can go with log and we can cancel log the error and again let me send one more time and in the console you'll see the error and again it is thrown by our library notice here legal arguments undefined and i just find it easier to check it right over here or something we'll learn later to set up a validation layer and again that is all coming up for time being i just find it easier to check for that error right here for those empty values and then just send back the response instead of chasing it in error handler can that just my preference of course if you don't like this setup you don't have to use it but that's my explanation for using this bad request over here hopefully everything is clear as far as the register and login and now of course we can move on to our next step all right and once the login register are in place as far as auth the last thing we need is auth middleware where we can verify the token and if everything is correct and get the user id and pass it along to the job routes now the functionality is going to be exactly the same like in the previous project i might just use different variable names here and there and to answer your question yes i'll purposely retype everything from scratch just because i find repetition to be very important aspect of learning now if you don't agree with my opinion essentially you have two options you can just copy and paste the code from the previous project and i'll show you of course where you can get it in a second or make this a challenge and try to recreate everything from scratch yourself and of course if you get stuck utilize the previous project code or this video lecture and of course the code that i'm talking about is this one if you navigate to folder number five the jwt basics one and then more specifically if you look in the middleware of course you'll find the middleware that we are about to set up and now of course i'll close everything and i'll start from scratch so i'm looking in the star looking for the middleware and i'm going to go for my authentication one and first let's start with imports and essentially we're looking for the user first so that's going to be our model so let's go with require and i believe this was two levels up so let me look in my models and of course user okay that's good then i want to go with my jwt because of course we want to verify the token so let's go over here with require and the package name is jsonwebtoken and the last thing that i want is the unauthenticated error which of course is coming from my errors and this is the case probably where it's going to be faster if i just copy and paste so let me take a look at index.js and of course the name is right here so let me import this from my errors and again i think i'll have to go two levels up so let me take a look at require and we're looking at the errors folder and since we have index.js you already know that we don't need to specify the path we just simply say errors and with all of this in place now of course what we want to do is go with const auth so that's going to be our middleware and of course it's going to be a function and it's going to be looking for three things the iraq res and next and then as far as the function body remember the first thing we want to do is check for the header so let's add here the comment and we're looking for a header first for the authorization one and then we want to check whether it starts with bearer so first i'm going to set up the variable and i'll say auth header and that is equal to require errors and the authorization one of course and then after that i'm looking for if statement and in here i want to check if it doesn't exist if there is no header then of course we'll throw the error or if it doesn't start with better so let's go over here with mouth header and we'll go with starts with so of course that's the javascript method that we can use on a string and then we go with better and in some setups you'll see this space added as well but honestly it doesn't really matter because remember once we are done with if statement we're still getting the token and if there's going to be no space then of course the token won't make sense we won't be able to verify the token we're splitting the token anyway and let's go over here with throw new and of course we're looking for on authenticated error and as far as the text let's go with authentication and invalid and you know we'll also need to add here async so let's add over here async now we're checking for the header as well as the bearer and if one of them is false then of course we throw the error and once we're done with that let's go with our token so let's say kant's token is equal to auth error and then remember we're splitting it and we're splitting it on the empty space and then we're looking for the second value that's why we go with one so we turn this into array and then we're looking for the second item in array and this is what i'm saying so even if you omit this and if you just check for the better if the user has sent bearer and then right away token well this one won't make sense because basically this will be undefined we won't be able to split the string and of course if that's the case we won't be able to verify hopefully that is clear so let's go over here with try catch and then as far as the try block we'll try to get the payload so let's say over here payload and remember the method name is jwt and verify and here we want to pass in two things we want to pass in the token comma and then of course we're looking for process dot env and then jwt underscore secret and now of course once i have the payload i just want to pass it along to the job routes and in order to do that we'll first add a comment attach the user to the job route and then as far as the logic we can simply set up a reg.user so i'm right away setting up the property on a request object and as far as the value is in there i'm going to go with user id again that's just my preference and then i'll go with payload so this is what i'm getting back from the verify and of course in there i'll have the user id as well and technically we won't use the name but just for testing i'll pass in the name as well so let's say here name and again we're looking for payload and then that name and again if you're a little bit confused essentially in here we're just getting the payload that we're setting up in the route so if we take a look at our index routes i'm sorry not the index roads if we're looking at the author outs and notice here when we're creating the json web token right now of course the functionality the actual functionality is in the model so let me go over there in the user essentially this is what we're passing in we're passing in the user id as well as the name so in the authentication middleware of course this is what we're getting back and again this is just for testing essentially in our controllers in the job controllers of course we'll just use the us id but since i want to showcase that this is actually the same user also pass in the name here as well and then as far as the catch well we have the error and we can just throw it we can just say over here throw new and we'll go with our error and essentially the text is going to be exactly the same so i'll just take it from here and copy and paste and before i let you go of course remember that we need to do two things we need to export the auth as well as we need to invoke the next because otherwise we won't get to the job routes anyway so let's go over here with next first so now of course we pass along the user to the job routes and we need to go with module exports and then we're looking for auth and i'll set up the actual middleware as well as test it out in next video all right and once the auth middleware is in place now of course we just need to decide where we're going to place it because if you remember the previous project we only had one authenticated route and of course we just used the router for that and technically we can do the same thing over here in jobs but we just need to understand that of course in this case we want to authenticate all the routes so basically we want to protect all of them because if i create a job i only want to look at my jobs and i don't want you to modify my jobs or you probably don't want me to modify yours so essentially what i'm saying we want to add that protected route for all of them so we want to protect all of our routes as far as the jobs not just one of them so technically you can say yeah well okay we can import and then we can just add them one by one and technically it is an option but there's actually a better one if we go to app.js take a look we have app.use and then of course we have all the job routes and in this scenario what we can do we can just get the middleware and then stick it in front of the jobs router and with that in place all of our jobs routes will be protected so instead of going one by one we just do that in app.js and as a result we'll protect all the job routes so let's do it we're going to go where we have the connect and above or below doesn't really matter i'll say authenticate user and we'll go with require and of course i'm looking for my middleware and in there i'm looking for authentication one and then we scroll down we go with authenticate user pass the comma and we're good to go and in order to test it we'll go to the controllers over here and since we'll start working in create job anyway i'll look for create job and we'll just test it out and we'll test it out in the following way where i'll go with res.json and let's just pass here rec dot user so i'm getting that user from my auth one if everything is correct and of course i should be able to see the user as well as the id so let me save it over here and as a side note i actually removed all my current users e in the database just so we can start nicely from scratch because as we were setting them up we used the dummy string and then we set up the proper one just so we don't get any dumb bugs i also suggest to do the same work remove all the users and we'll start everything from the scratch so now of course i want to go to the postman i already have the register route correct so let's just get the token first so of course i go with name email and password i get the token awesome that's what i wanted and now of course we want to set up a new route now again this is going to be a post route to create a job so let's go over here let's say new route we're looking for the post method and we use the same url of course and then if you remember the difference was that for jazz we just go with forward slash and jobs and if you want to double check just go to app.js first notice that's the path again this is already part of our variable the url one then we have the jobs and then of course in the routes as far as the post well that's going to be a route anyway so that's going to be the forward slash now for getting the single job deleting and all that then of course we'll pass in the route parameters as well but for the post it's simply forward slash which just means that we go with url and then the jobs now we're really not concerned with the body because we're just testing whether our authentication works but what we do need to get is authorization over here and my apologies i'm actually looking for the headers and the reason why i'm showing you the authorization because at the end of this project or maybe in few videos i'll show you how we can set this up dynamically so you don't have to every time just copy and paste the user token because we need to understand that of course we can use multiple users correct and you don't want to copy and paste every time that token so i'll show you a dynamic way how we can set that up but not yet so let's go here where we have the headers again we're looking for the authorization one and then we want to go with bearer and we want to pass in the token and once i send if everything is correct check it out i have the user id which should match to whatever id i have in the database and of course i'm not going to check value by value but hopefully you understand the idea where these ones should match this one and the one that i have over there on the postman and i can clearly see the name so what happens if i go with different user if i register this user instead and let's go with anna here again the same secret we get different token and now of course we should get different name correct so in the jobs i'll remove the john token and i'll paste the ana one once i send of course now i get back the ana so what that means in any of the job routes i'll have anna's id or john's id or whichever token i'm getting and when it comes to any of these functionalities will only deal with the resources that are associated with a user hopefully we're on the same page and now of course we can start setting up the functionality and once we're done setting up our auth middleware i also want to mention something where as you're looking at someone else's code you might come across this syntax where instead of creating a object like we are doing in line 20 what they do is they look for the user in the database so they take the model the user model and then either find by id or find one that also works and then of course they just pass in the id that is coming from the token and in most cases they will use the select to remove the password there's really no point to pass this password to the upcoming middleware meaning our request and therefore they just use the select and remove it and then when it comes to reg.user well i just set it equal to this variable and it's definitely an option but the reason why i'm not doing that in this project is simply because if we just think about it we really have no functionality to remove that user anyway so if i'm getting my id from the token i'm pretty sure that there is a user on the other side again you might see this code and yes we might implement ourselves in a future project but not in this case i really didn't see the point of looking for the user since we have no functionality to remove it in the first place now if you do decide to go with this logic then of course just make sure that you remove line 20 because otherwise you're overriding with our current setup anyway awesome and once our auth is working now essentially we want to set up a model for the job and of course work on rest of the routes now before we set up the model though let me also quickly save it so this is going to be create job so let's set up the name create job and of course i'll set it in the jobs one and i also want to test it out really quickly where if in headers i make that mistake and i don't add the space what response i get of course i have authentication error so again this just proves the point that i was making before where essentially even if we omit the space over here we still check the token and of course in that case we're not able to split it meaning we are splitting it but we're just getting undefined and as a result our token is undefined as well so hopefully that is clear so now let me just navigate to the models and i want to create a job model and the first thing that i want to do is set up the mongoose and of course that is equal to require and we're looking for a package the mongoose one and after that let's just set up our schema so let me close the sidebar just so we have a little bit more real estate so job schema and that is equal to new mongoose and schema schema and here let's pass in the object and as far as the properties i'm going to have the company and that will be equal to an object of course type will be set to string then required will be true and essentially we'll set it up as an array of course and let's just say true and as far as the message we'll go with please provide company and name and last thing that i want to set up for the company's max length that we can use on strings and in here we'll set it up as 50. of course if you want to go a different value be my guest so let me take the company and we'll copy and paste this one one time and the second property we want to set up is the position it's going to be a string again it will be required and in this case of course we'll say position please provide position as far as the max length in this case let's maybe increase it in my case i'm going to go 200 and then as far as the job interview well there's always this status whether it's pending so whether we're waiting for response whether we already have the interview or it was declined correct and essentially we want to do that using the status property so comma status and then again it's going to be an object it's going to be a string but we'll use that enum remember option where we can set up the array with a possible values so let's say here enum and as far as possible values like i said we'll go with interview then declined declined and then last one will be pending and this is going to be the case again where on the front end will just provide these two values the company one and position when we are creating the job so these are going to be the values that are required however the status one we will manipulate when we are modifying the job so therefore we'll go with status these are our options and then like i said lastly we'll go default and we'll set it equal to pending that's the setup i'm going to have and then probably the most most important property that we haven't set up is the created by why well because in here we'll tie our job to the actual user and the way it's going to look like we'll go here with created by again the name is really up to you but that's set up that i have created by and then type is not going to be string or a number in fact it's going to be a mongoose then types and then we're looking for object and id so this is very very important so essentially now we're tying our job model to the user one so we have the user model over here correct so this is where we're creating a user so every time we'll create a job we will assign it to one of the users and as a result of course our functionality will work because every job that we will create will be associated with a user so first we have a type and we need to go mongoose types and then object id that's going to be the type for our property and then we need to go with ref and we need to specifically say well which model are we referencing and in this case we'll go with user of course so i want to tie the job to the user hopefully that is clear and then of course we want to go with required as well because we don't want to create a job without a user we'll set it equal to true and then as far as the value again let's just go with please provide and user and then lastly right after the schema object the first option that we have over here i want to go with comma and we'll set up timestamps and true and i'll showcase them once we actually start sending requests from the postman because you'll see the benefit of using timestamps right in the response so don't worry about them for now i'll show you once we start getting back the responses and of course eventually what we want to do is just go with module exports and we want to set it equal to mongos then model and then as far as the name i'm just going to go with job and then we'll pass in the job schema and once we have all of this in place now of course we can focus on routes and i guess let's start with the create job one nice we have the model so now let's just set up the functionality for creating the job and then one by one we'll deal with the rest of the controllers as well and in order to set everything up first of course from the postman we need to send the data and what data are we looking for again let's jog our memory we have the job model and here i'm looking for the company name as well as the position now let's not worry about the created by yet since that one we will get from our auth middleware and in here let's just set up some kind of values in the body so let's go with raw and we're going with json of course and then here let's say company company and then i'm just gonna go with google because why not and then as far as the position well let's just go with intern so position and then we pass in the intern now let's go back to our controller where we have the jobs one create job and instead of sending back the user i want to send back the wreck that body again just so we can test whether everything works so i have create job route i send it here and of course i have invalid authentication because i didn't fix my better one so let me go back and let me just add that space and now everything should work where of course i'm getting the values for the company as well as deposition so now what's left to do is go back to create job and of course in here we want to import finally our model correct and we want to create a new one so let's do that we're going to go at the top here and we'll create our imports and effectively we're looking for three things i want to get the status codes i want to get the job model as well as the requests and for requests we have two options we have bad request error as well as not found one so let's go with khan's job so that's going to be my model so require and of course we're looking in the models here and more specifically job then we want to get the status codes so const and then status codes now that is coming from our library of course so require an http status code and then lastly we have those two errors so let's go here with bad request an error and the second one will be the not found one so not found error and both of them are coming from and of course the errors so let's go two levels up and we're looking in the errors folder and once we have all the imports in place we'll swing back to create job and essentially the idea is following where of course at the moment i'm just passing in the ragdot body e and the json response correct and if you remember what was the method name to create new document well that was of course create and of course in this case we're looking for the job one correct so the way the setup is going to look like we're going to go with job then we'll await of course and then we go with model name and create and we pass indirect that body but the moment what we're missing is that user and where is the user located of course it is located in the rec dot user now what are we really looking for is the id correct so what we want to do here is just go with rec dot body again if you want a console log of course you can definitely do so but i'm just going to skip that part and we'll go with reg.body then we want to create onrec.body a new property by the name of created by why well because in our job model that's how i called my property so i add this property onrac.body and where is it located it's located in rec user and the property name is user id like so so now of course once we pass indirect that body will still have the validations but if everything is correct we create a new job and now of course we just need to handle that as far as response so let's just set up res.status now again this is going to be the created one so let's go with status codes status codes then we go with comma or i'm sorry d dot and then we go with created and then as far as the json i just want to send back the job so let's go over here and let's test it out so now i'm getting back the company and position but if everything is correct i should get way more than that and once we send unfortunately instead of getting back to job i get back the error where it says created by and it is a validation error which actually just showcases that our validation still works which is really really good and the problem of course is in here where i went with reg.body and it should be created by not created by so let me save and let me test it out one more time and once i send now of course i'm getting back the job and as far as the job i have the status so like i said by default it's going to be pending so this is going to be the job id and this is very very important that's why on the auth i set up that user id and that's why also when i was setting up djs and web token i prefer using that user id once you start building a bigger application you'll get bunch of these underscore ids and it gets confusing quite fast and therefore i prefer setting up that extra piece of code where i go with user id or job id or whatever and if you keep looking at it okay you can see the google you can see the position all that is nice but you're also probably noticing the created by and essentially this points to anna and of course what that means is that now this job will always always be tied to anna so once i register and log in and get my token and all that i won't be able to modify look at it or whatever and you're probably noticing these ones as well the created at and updated that and effectively we get them by default once we set up timestamps as true so mongoose schemas have that timestamps option that tells mongoose to automatically manage create that and update it at properties on our documents so that means is that of course we don't need to set them up manually and you can probably already guess that this one will always point to the time when the document was created and this one will change as we're updating and of course we can use these properties for example in filters and essentially this is exactly what we'll do when we're getting all the jobs and once we can successfully get back our first job i want to congratulate you on pretty much getting over the biggest hurdle because from now on everything is going to be exactly the same like we worked in the previous projects the only difference of course as far as the controllers will always always get that user id as well because of course we'll need to use it to search for jobs to update jobs and all that cool stuff awesome and once we can create the job now of course let's worry about the rest of the functionality and let's do it one by one so next one up we have get all jobs now in order to get the jobs we already know the method that is find which is of course available on the model however in this case when it comes to the filter object of course we'll pass in created by property and we'll set it equal to the user because what we want is to get only the jobs that are associated with the user and i know that i keep pretty much repeating the same thing and my apologies for that but that is very very crucial in this case we're not looking for all the jobs like we did in a task we're only looking for the jobs that are associated with this user and as far as the functionality it goes something like this where we'll go with jobs that is equal to a weight and then we'll go with job find and remember the filter object and remember if it was empty then of course we're just getting all the jobs but that's not what we want in here we want to say created by and we want to set it equal to rec user and user id again that user property here is going to be on every request since in the app.js we placed our off middleware in front of all of our jobs routes and then let's also sort quickly and let's sort based on creator that remember this property the creator that let's sort based on that so let's say here dot sort and let's just pass in the property created at and as far as the response well let's just go with res dot status and as far as the status codes of course we'll be looking for okay one still status codes and then okay and when it comes to json response i want to send back the jobs as well as the count because that's what i'm looking for on my front end again this is really optional you can of course send just jobs but in my case i want to send both and once i have all of this in place now of course we can go back to the postman i'll save both routes the register user as well as create job and you know what why don't we create a few more jobs so in here we'll say apple and we'll say front-end developer developer and then let's create one more and this one will be facebook as far as the developer let's just say backend one so let's send it here and once i send i want to check my database and there i have jobs okay that's good and as far as anna i believe i'm setting up everything as anna i have the one for google one for apple as well as the facebook and once i have all of these jobs in place now of course we can create a new route so let me save it over here and let's just go with get route in this case of course and we're looking for url and this is going to go to the same one as create job so we simply go with forward slash and jobs and of course we just send it and if everything is correct we should get authentication invalid why because of course we do need to include the header so let me go back to the headers let's go to authorization so now of course we know that our middle works we cannot just randomly access all the jobs you can only access your jobs and then let's go with bearer and then let's pass in the token that we have for anna again i'll show you in a second how we can set this up programmatically so we don't have to copy and paste every time so let's say here bearer let's send and now of course i have jobs array with the count off three and i can clearly see that all the info is correct all right and once we can create the job as well as get all jobs why don't we set up that token dynamically in the postman because as we'll be creating more users and of course add more functionality it's going to get annoying quite fast if we'll have to copy and paste each and every time that token value and first what i did is saved the request the get all jobs one and as you can see that's the name and of course i saved it in jobs api and as far as the setup it's going to go something like this where we'll start in login user and then we'll repeat the same in register but for time being i just don't want to worry about setting up those unique emails so let's go over here where we have the login user and we're looking for a test and we just need to add a little bit of code first we want to access the response that we're getting back notice of course if we're successful if we have logged in then of course we'll get back to token correct and in order to get that we'll just set up some kind of variable in my case i'm going to go with json data and we need to go with pm so postman and then dot and we're looking for response and in there we have a function by the name of json and then let's just go with our token value and let's set up our global variable and notice here on right hand side we actually have snippets so if we want to set up a new global variable we just click it and now we just need to provide the values and effectively the name is going to be access token and then as far as the value this is where we go with json data dot and of course i know that in my responses token is going to be located in token property so simply go with a token and now of course once we send we should see in the globals a new variable and of course we do and the only thing that's left to do is to go to either get all jobs or create job doesn't really matter we can go here and instead of authorizing that manually i'll unclick it and then we're looking for authorization then we want to go with bearer so probably you have by default here this inherit just go to better token one and then as far as the value well this is where you want to access that global one correct so you just go here with access token and now once we send we should get back the job now of course i created with the same values if i check the body so i have facebook and backend developer so if i take a look at my database and if i refresh i should have two values i'll have one that i created before and the second of course was created when we're testing this dynamic setup and of course we can do the same thing with get all jobs as well so let's take a look we have the headers here and i'm sorry i'm looking in the wrong place so we have the headers here let's remove it let's check the authorization again we have better token we're using access token and then once we send in the body now we should get four jobs and in order for everything to work we also need to do that in the register user so let's go back quickly to the login one let's grab these two lines of code then we'll go to register one again we have the tests let's save it here as well and now let's try to create another user so let's go to i believe in the body right this is where we were creating a new user and i'm going to go back to my good old peter peter at gmail.com we send we get back the token and now the moment of truth if i create a job and let's just say in this case netflix and then it's still going to be a back-end developer now this one should be created for peter and again notice how we don't need to worry about those headers anymore so let's go back to our database let's refresh and if everything is correct i should have a user by the name of peter that i created of course there it is there's my peter and if i take a look at the jobs peter should also have a job so i keep scrolling and yes there is i have the netflix one and of course it is a back-end developer so if i take a look at get all jobs now of course i should get only one that is associated with peter so let me go back to get all jobs let me send and now of course i have count of one so hopefully it is clear that now we're dynamically setting that access token so you don't need to manually do that each and every time and once we have all of this in place now of course we can continue with our application beautiful and once we can set up the access token dynamically in the postman now of course let's keep on working on our routes and next one up we have get job and i think this is going to be the case where i'll actually log in back in as anna so where i have the login user out i'll just go with anna now of course i get this token just because she has more jobs now let me save all of these routes since i don't want to set up everything from the scratch and then once i have logged in as anna let me just double check get all the jobs yep i have four of them and then remember for get job what we'll need to pass of course that is going to be the route parameter correct this is where we'll provide the id and if you want to double check that just go back to the routes we're looking for the jobs one and notice so the post and get all jobs is for the root and then we have the forward slash and then colon and then the eddy of course this is going to be that route parameter which will get me that single job make sure that i can delete one as well as update one and in order to test it out whether our basic functionality works essentially whether we can get that silly string we need to go back to the postman and i think i'll just leave the login user one and then i'll open up a new tab we're looking for get request of course then we go over here with our url and then forward slash and this is where i want to pass in the eddy so in get all jobs as far as the response of course will get back those ids correct and now if i want that one single job i just need to take underscore id again you're not looking for the user here you're looking for underscore id which just signals a job id so copy this one then go back to the get one the one will get the single request and remember we still need to go with authorization we need to set up better token and of course we'll use the access token and once we send if everything is correct of course we should get route doesn't exist because i was pretty smart and i forgot to add the jobs one so let's go over here and let's say jobs and then once we send now of course we have get single job so we know that this functionality works and of course now we just need to go back to our controller and in here i'm going to be looking for two things in the request first we need to remember that as far as the jobs we can access it in the params object that's going to be the job id and when it comes to user of course that one is located in the user object that we're getting from the middleware so let's destructure both of these things because as our functionality gets more complex i think it's easier if we can clearly see where we're getting those values from so i'm going to structure my request object and in there i'm looking for two things i'm looking for the user object and remember in the user object i have the user id so now of course we're doing the nested destructuring so i'm looking for that first and then what i want is the params so this one of course is provided by the express and then more specifically we're looking for the id now why we're looking for id because that's how i called it over here and then since i want to have more clarity on which one is which i'll right away give it an alias of job id like so so now we have both we have the job id from the params so this one is coming from here and then since we have the access token now of course we can also access the id of anna and then it's simply a logic of finding that one job where the id is the job id as well as created by is equal to the user id and if the job doesn't exist then we'll throw this error because remember we have two types of error either we'll get a casting error where the syntax doesn't match to that of the mongoose object id or simply we just pass in some kind of wrong job id and then of course if everything is correct then we send back the job so let's try it out we're going to be looking for the job and that will be equal to a weight of course then we go with our model name and then we go with find one that's the method name and then in here in the filter object we pass in underscore id which is equal to our job id first now of course in here the order is not important but we do want to check for both otherwise somebody can just get the id and then they can access the job so let's go to created by and we'll set it equal to our user id and then like i said we have two options for errors either we have a casting error which will handle a little bit later as far as the nice responses or we simply have a case where we provided some wrong id and we'll simply check that by saying if there is no job then we'll throw our new error and of course we're looking for not found one and then we'll pass in the actual text with the job id so let's say no job with id and since i'm using template string i can right away access it and i'm going to be looking for my job id now if everything is correct then of course we'll get back the entire job so say here res dot status which we're looking for are status codes then we'll go with okay and then we'll go with json and i'll send back the job now of course we can just test it out in our postman where instead of this get single job i should get the job that matches that id in this case i'm getting the google one so now let me double check where i have all the jobs and i'm gonna be looking for well these ones technically are both the same so let me look for the apple one and i'll grab the id that's the job id again keep that in mind that is very very important we're not looking for the user id and once i send of course i should get back the apple and if you get the same results then of course we can move on to our next step awesome and up next we have update job and essentially i can tell you right away that a lot of the stuff that we already wrote in get job will repeat over here so therefore in order to speed this up a little bit of course i will do some copy and pasting here as well and in order to test it out i'm just going to navigate again back to the postman this is where i'll start i'll save this one first the single job one so get single job single job and then let's create one for patch meaning one for update but of course the method will be patch and i'll leave get all jobs since i want to keep using those ids of course and i think i can close the login one for now because we already have logged in as anna and then let's look for the patch method and ascended i'm messing up the get single job my apologies so let me open up the new one and i'm gonna go with patch we're looking for the url one and again we'll be looking for the jobs and then we wanna go with that route parameter and of course this is going to be that job id so let me get all the jobs and you know what i'll work with that last one since we have repeating values so let me grab here this id and then pass it here and remember authorization we go with better token and we have access token and if i send and if i get update job then of course we know that we can start setting up the functionality and as far as the logic like i already said i mean most of it is going to be exactly the same the difference of course is the mongoose method we're going to use and the fact that i'll check for both i'll check for company as well as the position and i'll check whether they are not empty and you'll see what i mean in a second so where i have the update job let's just start working and first same deal i'm going to be looking for the user as well as the params so that won't change because remember in the routes i mean all of them are looking for that route parameter correct so let's take this one there's really no point to repeat ourselves in this case so let's copy and paste however the difference is that in this case since we're updating also in the body we'll provide some info and in my case i'm going to be looking for both i want to get the company as well as the position so let's go here with raw and we'll go with json here and if you want to speed this up you can actually go to create job and just take these values so that's going to be our patch one copy and paste and we just need to remember to add the curlies here and as far as the values well let's come up with some kind of company and i'll call this random and then it's not going to be a backend developer so it's going to be a full stack and then back in my controller we also want to add it over here so i'm still the structuring the request object correct and in there i have params i have the user now as well as the body because remember in here we're sending that in the body so let's go back and let's say body and in the body we'll be looking for company company and position don't forget to add the comma and right after we structure everything i also want to check whether the company or the position is empty and if that's the case i want to send back the bad request so say here company is equal to an empty string or position is equal to an empty string and if that is the case i'm going to go with throw new and we're looking for bad request of course so bad request error and we'll say company or position fields cannot be empty let's save it here and then of course we want to use our find one and update and remember we need to basically pass in three things we want to pass in what we want to update we want to pass in which job we're looking for and then of course we also have options where i want to get back the updated version as well as i want to run the validators so let's do that however there is a tiny bug over here and essentially i'll come back to this one why i prefer setting up the check in the controller once we start talking about the mongoose errors and let's just go with cons job and we'll set it equal to a weight then job of course that's the model find one and update and then like i said first we want to pass in well which job are we going to update and the setup is going to be exactly the same where i want to look for underscore id as well as who created it so let's go here let's say underscore id is equal to my job id of course job id then we want to pass in the comma and we'll go with created and then buy now that is equal to my user id and then of course we want to pass in what we want to update so let's just go here with the rack and body and then we want to pass in the options and i'm going to go with new true so we'll be getting back that updated job and then i also want to right away run my validators and of course the property for that is run validators and we'll set it equal to true now if the job doesn't exist we already know what we can do we can simply throw a not found there and if everything is correct and of course we return the job so let's scroll down copy and paste and our functionality should be working where if everything is correct i'll get back the updated job if not then of course i'll get back the error so let's test it out right now in the postman so i'm going to go with full stack developer and you know before we send the correct request why don't we remove that last value in the id let's send it here and now of course we're getting back that massive mongoose error that we'll work on a little bit later and then if i just change it around to four then of course i'll get back no job with id such and such so let me change it back to three i think that was the correct one and now once i send now of course i am the company and the position is full stack developer and with this in place we only need to worry about remove job functionality beautiful so now let's just set up remove jump functionality and i guess let's start by saving our request in the postman so again we go with save as or just control or i believe command s and then let's just write up the job update job and of course we want to set up the same thing for delete job and let's just start everything from scratch again we have a new request we're going to go with delete and then the url is going to be our global variable then forward slash jobs and now back in get all jobs why don't we remove that random one so if i go with get all jobs i can clearly see that i'm getting back the random job that's the one that we just updated so why don't we remove this one so again i'm looking for underscore id i'll right away set it up as my route param and as far as the logic well we're not going to be setting up anything in the body we really don't need to what we're looking for of course is the authorization again want to go with pair token access token awesome let's send we should get back delete job and as far as the functionality again we're going to be looking for user and params both of them are located in the request correct so one is coming from auth middleware and the second one is coming from the params again i know this is a repetition but it's very very important that we understand that then let's copy and paste so we have access to both of these ones then as far as the method name we're looking for find one and remove so let's go here with const and we'll set it equal to job and we'll set it to a weight and of course like i said job and then find one and remove that's one we're looking for and as far as the filter object let's just go again with underscore id and then job id of course and the same goes for the user id created that or sorry created by and then we set it up as user id and the same deal if the job doesn't exist then we send back the error and if everything went smoothly then we simply want to send back 200 that's all we have to do and i'll do that by cheating a little bit where i'll take this code from the update one and just copy and paste so we're throwing the error if there is no job or if everything is successful we don't need to actually send back the json again that's really going to depend on your front end but in my case i'm just looking for that 200 so if there's some kind of error then of course i have one functionality on my front end however if everything went smoothly if i remove the job then of course i'm just getting back that 200 that's it so now of course let's test it out in our postman where we have the job we want to remove it let's send it here as you can see i'm not getting anything back but i have 200 which is always a good sign so now of course let's go to get all jobs or you know what let's save this one first let's say save as and say remove or delete job it's really up to you delete job save it and then when it comes to get all jobs of course i can send it and count is back to three when it comes to anna and with this in place let's just quickly try out to log in as peter so we just simply want to change the name here i'm going to go with peter the password is still the same and of course i just need to be correct with my email i send it yep i get the token and now let's take a look at all the jobs that peter has and of course it's only one so now let me grab this id and first i'll change it so first we'll go with update and as far as the body i'll just pass in random and when it comes to your position i'm gonna go back to the internal one in turn here so let's send it that's the response i have company random and of course i want to also see whether i can delete it so when it comes to delete job i'll take the same id i'll go back here i'll copy and paste and once we run get all jobs for the peter now so let's go back to all the jobs and once we run it now of course we have jobs this empty array and count is zero but keep in mind this is still a successful response it's just peter hasn't created any jobs or in our case we created it and then of course we removed it and with this in place we're done setting up the core functionality for our application beautiful and before we worry about deployment let's make our mongoose error responses more user-friendly and before we start let me just say that just like our error classes we will only do this once and after that we'll bring it from project project so if at some point you get bored just remember we only need to do that in this project and then for remaining projects of course we'll just reuse the code and the idea is following where currently we have three mongoose errors we have validation one remember that is if the user doesn't provide one of the values then we have the duplicate issue where email is unique and of course we also have the cast error and if you remember that's when the id syntax doesn't match exactly to what the mongoose is looking for we want to go to the middleware and more specifically we want to go to the error handler and of course at the moment i'm logging the error and in here i'm just sending back this generic response so internal server error and i'm just passing in the object and if i take a look at the postman i'm going to be looking for register route and then if i have already a user in this example susan so if i already have that email and if i try to register one more time of course i'm going to get that duplicate error correct because i already have the email in the system and essentially the goal is following where we want to send back more user-friendly response and also we want to change the status code because at the moment we're just sending 500 but of course this is 400 this is bad request and the way we do that we navigate back to error handler material and we'll start by creating a object a custom error object and the reason we'll do that because we'll set up multiple if statements now technically you can also manipulate this code and i'll show you in a second why and how but in my case i'll just leave it the way it is so if our error is our custom one basically if it's one of the classes then we'll just right away send back the response if not there's going to be a new custom error object and then as far as the response we'll send back that object instead so let's start working on that and essentially we want to go with some kind of variable in my case i'm going to go with let just so i know that i'm going to be manipulating those values and i'll say custom error and that one is equal to status code and the message so here i want to set up two properties and basically we want to set defaults so the same idea if there's already something provided then of course we'll send back that if not then there's going to be some kind of default and effectively it's going to look something like this where we'll go with the property name so status code and this will be equal to error and then the status code and eventually there's going to be multiple if statements that will manipulate this value so in here i'm just setting up the defaults i say hey listen if in the error i already have the status code then use that if not well then let's set up the generic response let's say status codes and we're looking for internal server error and that of course is going to be 500 and let's do the same thing with the message so message property and error and let's just say here message and let's go with two vertical bars and we'll say something something went wrong and let's say try again again later and now of course what we want to do is change this code around where instead of sending this internal server error and json and error of course we'll use these values instead now i will still leave this code meaning i'll just comment this out so copy and paste and comment down just because i'll be sending those error object back to the postman because i find it easier than logging in here and chasing it around the terminal again that is just my preference and essentially what we want to change over here is the error now of course we're looking for custom error and then we want to go with status code and then as far as the json well the same thing we're going to go with message and we'll set it equal to our customer dot and of course we're looking for the message and you'll notice that at the moment there's really no difference so if i go back and again try to register susan even though the email is already news i see this one i see over here a message and this is going to be that mongoose one and of course i still have this 500. so technically nothing changed now of course this is where we'll work on right now where after our custom api instance we'll go here if and essentially if you want to check we'll have to take a look at the object one more time so this is why i'll keep both of these responses because it is hard to find that error over here and essentially i'll be sending back the object just so you can see what is happening and i think for time being i'll get the error so let me just save it here let's send one more time and what you'll notice that of course if we have that duplicate issue this is the error that we're getting back and effectively what we want to do we want to check if the error code exists and the code is equal to this 11 and then three zeros then we want to send back this value this email one so then we want to access this key value and then just come up with some kind of message so it's going to look something like this where we're going to go with if then like i said we're checking for error code and keep in mind that i'm not talking about custom error here i'm saying yeah there is a error object and now i want to check whether it has the code property and if it has then i want to check more specifically if the value is equal to 11 and then three zeros so go over here like this and then if that is the case then i know that i can access of course this key value property and i just need to come up with some kind of message now what we'll do over here like i said we'll modify these values over here so in here we just set up the defaults if the error is not going to match any of our conditions then either we'll use the actual error status code if it exists as well as the message if not then of course we'll have these defaults hopefully that is clear and let's just start by setting up the message now how we can do that well we can go with custom error so that's our object and essentially we're overriding the message correct i'm just saying the message value will be equal and in this case i'm gonna use the template literals because i'll pass in the actual arrow key value and as far as text i'm just gonna say duplicate value and third four and now let's access the value let's say error and again remember we're looking for this property over here correct so say here error and we're looking for key value and then we just want to continue with the text so field please choose another value another value and of course i also want to change the status code so in this case i'll go with custom error and i'm looking for status code property and i'll set it equal to 400 because this is a bad request and since we can clearly see the error object since we already have all of the code that we need again i'm just going to hop around here and i'll comment this one out because i will use this one in a later videos and then we'll go back to this custom one and once we set everything up now of course we can navigate here we can send and of course this is the response so now we have the message we have duplicate value entered for object object and we'll work on this one a little bit later and what's really cool that of course now we have 400 so we can clearly see that it is a bad request now if we don't want to send this object object which of course is not that helpful we'll simply need to use a little bit of javascript but of course we have the object so our key value is an object and in javascript we have object dot and of course in our case we're looking for keys so this will give us a array of keys and of course in this case we'll only have the email so it's going to look something like this where we go with object keys and then we'll pass in our error and key value and as a result we'll get back array of the keys so let's send one more time let's go back over here and now of course we'll have duplicate value for the email field please choose another value and with this in place now we're handling the duplicate error and essentially we're sending back more friendly user response awesome and once we check for duplicate value now let's quickly talk about our custom api ones so our classes and we can actually remove this if statement right now because remember in the custom error we are checking for the status code so if that property is on the object then beautiful we set our status code value and the same goes for a message and in order to showcase that i'm just going to remove this if statement for time being i'll just comment it out just so i can always put it back if i'm wrong and then as far as the route well let's take a look at our auth chairs and i believe we're using it in a login correct we have our bad request error so let's try it out now of course i'm going to go to login user and i'll try to get the token for susan without providing the password so let me remove it let me send it over here and now of course i still have please provide email and password and of course the error code the status code is also good it is 400 which simply means that of course our logic works because again we have this custom error one and essentially we're looking for a status code property on the error object that's coming in because remember in here of course we're setting up a new one and the same goes for a message so you can simply remove this code now i'll leave this one for your reference just in case you want to use it but effectively we don't need to use this anymore and of course with our new setup we don't need to import the custom api our class as well so you can remove it and the code will still work not bad not bad in our current setup we're nicely handling duplicate values as well as our own custom errors so now of course we want to deal with those validation errors which of course is the case for example in the auth when i'm registering the user and i'm right away passing in direct.body so i'm not checking for email or password or name over here i simply let the mongoose handle that and the way we do that is pretty similar to what we have over here we simply want to set up the if statement again we'll have some kind of condition in this case we're going to be looking for validation error and if that is the case again we'll use one of the nifty javascript methods in this case we're not going to be looking for keys we'll be looking for the values and of course we'll send back the nice response and in order to test it out let's just go back again to our postman now i'm not going to do that in login because again in here we have our custom one the bad request one what i want to do is go back to the register user and here i want to remove both the email and the password and yes i'm purposely removing both just so you can clearly see our functionality in action and once we do that once we send i mean we can still see 500 so that just means internal server error but the message is already more user-friendly correct we already have user validation failed password and blah blah blah so let me show you the entire object just so you can understand the functionality we're about to set up better and technically i don't even need to comment this one out because if i have my first return of course this is what we'll send back so let me go back to the postman send it one more time and of course this is going to be that giant object that we're getting back and the structure is following where we have this errors object and of course in here we'll have all the values that are missing so of course in our case that is password and the email and this is very very important because of course if you have only one then technically you don't need to worry about multiple keys but that's not our scenario so in our case we do need to worry about multiple keys in that object because maybe the password email and name might be missing and also in that object in the error object not only we have errors we also have the name and essentially in our if block we just want to check whether it is a validation error so let's go back and i'm going to do that above the duplicate one but of course the position doesn't really matter where i'll say error name if it is equal to the validation error so let's go over here with validation error and if you need to copy and paste just so you don't make some silly typos so essentially if you're like me then of course you can do that so let's copy and paste and if that is the case then what i want to do is get all the values for the keys in the errors object so notice of course i have the password correct of course i have the email and what we want to do grab this errors one and just get the actual values of these objects because errors is an object itself then password and email are object so i'm looking for the actual values in there and you'll see what i mean in a second so i have if error name is equal to validation error then let's just go with custom error and we're going to be looking for the message and like i said we're going to go with object and values and then we'll pass in the error and errors so in the error object of course there is errors object and in there i have two more keys we have password and email and i want to turn them into array and then i want to iterate over using map so since we're getting back the area of course i can use my map method and i'm just going to call this item so each and every item i'll call the item and then i'll say item.message so in here you'll notice that of course in there in that values i have a message property correct and then i want to access it and send it back so let's say here item dot message and then we'll just join it back to the string and we'll add a comma so that's going to be our message now as far as the status code again 400 so let's go over here with custom error and we're looking for status code and that will be equal to 400 so once we save and once we send it back now of course we should get a better response but of course we don't because i mean i left my first response in there as well so let me comment this sucker out and then send it here and now of course i have please provide password please provide email which effectively is way more user friendly than the object that we're sending back and also notice the status code of course now we're sending back 400 and if you're confused about the code just go back to the error handler and just log what you're getting back from object that values and it will make total sense so essentially the map and join will make total sense so let's try it over here we'll go with console.log and then we're looking for object dot values and then here we want to pass in error so the error object and then more specifically the errors object so let's save it and back in postman we want to send it of course response doesn't change but in my terminal i can clearly see that what i'm getting back from object.values is array of objects and then i'm iterating over that array and then more specifically in each object i'm accessing the message and then i just join all of them together so i set it back to the string and then i just add comma e in between and once we have all of this in place now of course we can worry about our third instance and that's going to be the cast error and as far as the cast error of course in the auth we're not going to get it because we're not using the ids but in the jobs we should get it so back in where i have the jobs controller if we take a look at i don't know get single job of course i'm passing in the job id that is coming from params correct and here if i cannot find the job that has the job id with the user id of course i send back the not found error however there also might be a case where the syntax doesn't match to whatever the database is looking for and of course in order to showcase that let me just go to get all the jobs so this is going to get me all the jobs that susan has and as a side note i think i logged out so let me log in back as susan so let's say over here password and in my case while i'm testing and pretty much setting everything up as secret so let's send it here yep we have the tokens so let me now send get all jobs okay awesome i'm getting the jobs and now of course whether that's for get single job update job or deletion i will have to provide that id and if i'll just mess up the values that's one thing then we'll get that 404 but we also might have that cast error so let's go to i don't know get single job copy and paste the correct id send here okay we should get back the correct response but if i'm going to start adding the values who are removing we should see the casting error now again in our case we just see the string so let me scroll down i know it's a little bit annoying but it's important for me to showcase those big objects just so i can see where we're getting the values from and once i send it of course now i have error and the name is equal to cast error and now we just want to swing back to our error handler and essentially set up the if condition where i'm going to be checking for cast error if that is the case then of course i'll just send back some kind of string with 404 so again that's going to be not found one and i'll just provide the value just so user can understand what's happening so let's go back over here let's say if and i'll just say error name and if it is equal to a cast error and if that is the case i want to go with my custom error then the property name is message and actually i want to set it up as template string so no item found with id and then we're going to be going for error and of course i'm looking for the value one so in the our object there's a valid property and i'm looking for this id so let's say here error value and then the next thing is that status code and in this case we want to go with custom error so custom error here and status code and that is going to be equal to 404 or not found now of course if you want to use the status quo here as well please definitely do so i just thought that it's important for me the first time to show you the actual number status code and then if you want you can use the library instead so let me send it here and of course i should get back the proper response but problem is that i'm still sending back the first one so now let me remove it since we're not going to use it let's save it and then once we send now we have no item found with id and we have the 404 and with this in place of course we can move on to the next topic all right so for all our apps were nice and cute since we only use them in local setup but with this project things are about to get interesting you see this app will actually host on heroku basically deployed on the cloud and what that means that we also need to think about security essentially how we can protect our api from some bad actors and the good news is that with the help of community so think npm and more specifically npm packages we really don't need to do that much just install some packages and add them as middleware in our app and we're good to go yes it is that simple now is our app going to be safe from any possible attack well no most likely not remember our biggest security soft spot is still our user yes of course we should be protecting our api but how are you going to stop the user from storing a token in a unsecure manner there's really no package for that and as far as the packages we're going to use well first we're going to use helmet arguably the most popular security package out there which sets various http headers to prevent numerous possible attacks in fact helmet is so popular it's actually used in many other packages as a dependency after that we want to implement coors library which just ensures that our api is accessible from different domain if you don't have cores installed you'll only be able to access the data from the same domain if you remember in the previous project we did that in javascript file located in the public folder and if you try to access our previous apis from any other frontend apps you'll get a course error now coors stands for cross origin resource sharing and it is a mechanism to allow or restrict requested resources on a web server depending on where the http request was initiated by installing and implementing the course package essentially we make our api accessible to the public after that we want to use xss clean library which sanitizes the user input in reg.body reg.query and reg.params and as a result protects us from cross-site scripting attacks where the attacker tries to inject some malicious code and lastly we want to limit the amount of requests the user can make and we'll do that with the help of express rate limit library if you're using the star all libraries already installed and ready to go but if you want to use it for your own project of course just install them by running npm install and then name of library and also if you want to get more info on any of them a library docs is a very good place to start in later projects we might use some additional libraries or config options but in general as far as the standard security this setup is a very good place to start all right and once we have covered general info about the security packages now we simply want to go to app.js we want to import them one by one and of course we just want to invoke them and in my case i'm going to do it over here where we have express.json and i'm going to start by providing comment extra and let's say security packages and then we're looking for helmet first and we'll set it of course equal to the package helmet then the same for cores so this is the course package and we have one for cross-site scripting so require and the package name here is xss clean and last one is express rate limit and i'm purposely setting this one up last just because there's going to be a little bit of configuration there as well so let's go with require and express rate limit then let's save keep scrolling where we have the json let's start with our helmet so app.use and like i said we just invoke the helmet the same for rest of them so i'm that use and of course in here i'm looking for cores i can just copy and paste then i want to go for cross-site scripting one so xss and again we invoke it and then we add limit1 so again app.use then rate limit and you know what i think i'm going to change the name here i'm going to go with rate limiter not a big deal but just my preference and if we take a look at the package docs effectively what we want to set up is the time so in how long and how many requests and as you can see here they provide an object and properties are window milliseconds so effectively we get this in milliseconds and we just set up time and as you can see this is example for 15 minutes and then how many requests and also if you keep on scrolling you'll notice their responses so by default the message is going to be too many requests and the error response is going to be 429. and once we're clear on setup let's implement it in our own app so first what i want to do is move this rate limiter up so i want to set it up as our first middleware and then in order to speed this up we'll just grab the object here with those milliseconds as well as the max request we'll invoke it here copy and paste and our limiter is in place lastly according to their docs if our application is behind reverse proxy which is going to be our case since we'll push this up to heroku we also want to implement this app.set trust proxy so let's just take this code and place it before the rate limiter and with this in place we have our security packages so now we can move on to our next step just a friendly reminder that we're about to host our project on heroku and if in the mongodb you are using local ip address option you'll need to switch to allow access from anywhere one otherwise mongodb will throw an error and your app won't work awesome and once we have the basic security in place let's complete this project by deploying it on a cloud so we can start utilizing our api from any front-end setup and while there are many hosting providers out there during this course we'll use the following two heroku and digitalocean they both have their pros and cons so just like in most cases at the end of the day everything depends on your own preference and for this project we'll use heroku and since it offers generous free tier in order to follow along you'll only need three things an existing heroku account and of course the sign up is free so just navigate to heroku.com and look for signup option second since heroku utilizes git version control you'll need git installed on your computer and since this is somewhat of an advanced course my assumption is that that is already a case my assumption is that you already have git properly installed and third you'll need a heroku cli a tool to deploy our apps right from our computer and as far as the install for heroku cli you can find the entire setup in the heroku docs so once you sign up for the account this is going to be your dashboard and of course i already have some apps in there and you can find the cli install by clicking on the docs and more specifically the heroku cli link so let's click on a docs and then like i said we're looking for roku cli and in here just pick the operating system and follow the steps once you're done with an install make sure to double check whether everything went smoothly by typing heroku hyphen v in the terminal and if you can see the version number great feel free to proceed to the next video if not if you don't see the version number please troubleshoot since you'll need a working heroku cli in order to follow along with the deployment so if i go back to my terminal and if i type heroku hyphen v of course i can see the version number which means that i have a working cli on my computer and lastly in the next video we'll actually deploy our app and during deployment we will utilize some common standard git commands like init and and commit and since this is not a git course i'm not going to dwell on them too much so if you need to jog your memory as far as the get basics please utilize the search engine all right and once you have installed heroku cli now let's finally deploy our application and in my case what i'm going to do i'm going to look for the entire folder so this is the entire course and then for the jobs api and after that i want to get the final one and essentially i will make the copy just so i can set it up on desktop now of course in your case that is going to be your current application however i do strongly suggest following all the steps and deploying the project as a separate project and here's what i mean so i'll make the copy of the final one here and i'll rename it but before i do that i'll just drag and drop and place it on a desktop so here now it is on desktop and then i'll call this jobs api or whatever again the waste name is really up to you and i suggest doing the same thing essentially if you have been working on starter just make the copy and set it up on desktop or somewhere separately because it's just going to be easier otherwise if you're working in the entire course project in my opinion it's going to be hard to navigate around and set everything up and you also might run into some bugs so let me open up right now my text editor i'll make this one a little bit smaller then i'll drag and drop my application and effectively will follow these steps so let me go back to heroku we'll go to documentation here and then we're looking for node.js and then more specifically we're looking for deploying node.js apps on heroku so these are all the steps we're going to take plus some additional ones that i find useful and first what i want to do is go back to my project and i always always always start by removing the existing git repo just in case there is one and as far as the magnet command is rm then hyphen rf and then git now if you're using windows if you take a look at my twitter if you look around you'll probably find one of my tweets where i share both the command for windows as well as the mac again this is very very important you always want to start from the scratch after that we want to check whether we have that process dot env port variable and by the way by the end of deploy i'll show you where we can actually see the value that is on heroku but this is a must again we can hard code and it nicely works in a local setup but when you deploy you always want to go with process.nv and then the port variable and then heroku picks that port variable and of course spins up our application on that port then we want to set up a simple route so at the moment we have the auth and jobs but what i also like to do is just to set up a simple dummy get road so i know that everything is fine and i have deployed my application and in this case i'm just going to go with app.get then forward slash so of course that's my index and then i'm looking for rec and res and then here let's just send a silly little response where we say res dot and say send and jobs api that's it that's all we have to do and then we will navigate to package.json and this is where we'll take a look at the steps so let's keep on scrolling and they suggest setting the node version and in my case that is node 14 because remember initially when we started the course i installed note 14 but if you install different version push set that one up and just to jog your memory if you want to check your node version just go to node dash nv and again my case that is 14.15 but essentially we'll just go with 14. so in the package json keep scrolling then add a comma and then let's say engines and then inside of it let's go with node and pretty much set up the same code so in order to speed this up i'll just copy and paste and i'm in good shape then let's scroll up and where we have start command we're not going to go with nodemon app.js this is of course only in development effectively we'll go with node and app.js then save it so that should do it for package.json and then lastly as far as the initial setup we want to set up a proc file and then add some values to it now if you want to find more info about the proc file just keep scrolling here blah blah blah and i think i already went past it so let me go up notice here specifying a start script and if you click on this profile you can find more info but effectively what we want to do is create new file now we don't add extension here we just say proc file like so and then inside of it we'll go with web and we'll set node and app.js so pretty much this value is going to be the same as our start command and that should do it for initial setup so now of course we need to start working with git as well and first we'll start by git init so we'll initialize empty git repo then we want to add everything to the staging area so git add and then that and then of course some kind of commit message so essentially in this case i'm going to go with initial commit okay awesome and then this is where the heroku comes in we want to go with heroku and you know let me just clear everything so you can clearly see what's happening so we're gonna go with heroku and login so if you have the cli you'll be able to log in just press any key like this suggest over here and then once you do that they'll ask you to log in okay then of course we want to create a new heroku application and we do that in the following way we go with roku and again let me clear everything let's go with heroku then create and then we need to come up with a name and keep in mind that you cannot start with a number so if you remember in our course project of course i go zero 0605 or whatever in this case i'm gonna have to go with jobs api and then this probably will be taken let me double check yep notice here he's already taken so we need to start from scratch so let's say heroku create and then i'm gonna go jobs iphone api and then zero six again you cannot go zero six and then jobs api it's not going to work because you cannot start with a number so let's set it up now i'm creating that new application awesome and as i said if you just run heroku create it will create a name for you so if that's what you prefer i mean go for it and then i just want to quickly check whether git remote points to the actual repo so let's say here git remote and then hyphen v and if you see these values then of course we are moving in the right direction and before we can push this up we need to of course deal with our env variables correct because if you take a look at the get ignore of course these are ignored and that's how they should be and effectively we have two ways we can do it using command line but i'll just add one value using the command line i'll just go with this lifetime one and then i'll show you another way how we can do that e in the dashboard on the gory because i find gui to be easier as far as setting up the env variables now with that said of course that means that initially when we push our application to the github it's not going to work because our application is looking for all the nv variables but i'm just going to show you one the lifetime one because if you'll try to do this secret essentially in the command line it's just going to be spinning back errors as far as the secret value now of course you can always switch back to string the i don't know secret jwt or whatever but since i want to keep this value i'll show you both setups and after i've been rambling and rambling for about half an hour about it let's go with heroku then config config and then we want to go with a colon and set and essentially this is where we're going to set up those env variables and yes for all the env variables you have you'll have to type this heroku config and send it by typing as always is awesome so let's go with config and then set more properly and then copy and paste and by the way didn't copy this one either my apologies i'm literally on fire so let's go back here and then copy and paste and now of course we're setting that config variable correct so now we have one the jwt lifetime and 30 days so without setting up these ones we'll push this up to the heroku of course our application won't work but then i'll show you another way how we can set them up so now let's go here and in the command line let's clean everything and let's just type git push and heroku and then if you check the docs they say and by the way this is that login screen and close it but if you check the docs they say that you should go with heroku and main now in my case if i type heroku and main i'm basically going to be getting this error if i go with get push roku and master then everything works as expected now our application is being pushed to the github and from there of course the heroical picks it up and now it starts deploy but we need to go back to our dashboard our gui then in here we can refresh we should see the application but again it's not going to work if you go to application if you open app of course you'll have some kind of dummy screen or whatever but i can tell you right away that our application won't work because of course those emv variables are not there now in order to set them up in a gui we'll go over here and we're looking for settings and we'll go with reveal config wires and notice we have the lifetime one correct and now simply what we want to do is add the rest of the values as well so essentially here i'm looking forward to my uri that's going to be my first one copy and paste and the same goes over here so i want to take the value of course and copy and paste let's add this one and the same will do with our secret one and for some interesting reason in the console it spits back errors but in the gui when you add that secret one then everything works like peaches so let me go back here let me grab the value copy and paste and now of course we want to add that var and then in order to spin everything up we just need to go here more and we need to go with restart all dinos so at this point i'll freeze the screen i'll change back to my actual password and then i'll restart dinos and once we restart all the dinos yep that's what we want to do and if we take a look at the logs you'll see how initially our application was on port 43 710 so that was the port that the heroku picked then we exited with a status of 143 so basically we had the issue with our process.nv and now of course we're back to 46 and then 97 so that's the port if we open up the application notice i can clearly see my jobs api and of course i was just showcasing the port variable so you get the clear idea of how everything is set up that's why we go here with this port because then heroku picks the port where our application is going to be located and once i have my application up and running we simply want to grab the url and we want to test it out now i'm not going to test it out with all the routes but i definitely want to create or log in the user and see whether i can see all the jobs so in my case i'm going to go to the postman and since i don't want to mess up these routes i'll actually create first a global variable because in here of course yes i have the url but what is the actual url well it is localhost 3000 correct now what do we want to do we want to go with edit then let's write here prod and then underscore url and then let's just copy and paste the value so this is going to be the url for your application now we're still looking for api and then version one so that's not going to change let's save it here and then i can close my globals and like i said i'll create a new route and this is going to be a post route and since i have that one susan user i'll just try to log in and then see whether i can see all the jobs that susan has and in this case we're looking for prod and of course the url okay awesome then we're looking for auth and then forward slash login so that is going to be the url now as far as the credentials well where we have the login user first i want to grab the body here so let's take all of this and again we're just doing that so we don't have to type everything from scratch so json copy and paste okay we have susan gmail password and all that and then remember since i want to set that token automatically what do we need to do well we need to look for tests correct and just take these two lines of code and then back in my production one copy and paste and now i want to send and if everything is correct which of course it is i'm getting back my token and i'm still setting it up in the globals which is just awesome and now of course we just want to create another route now this will get all the jobs that susan has so let's go and go with get route and we're looking for again the production url then jobs and this is going to be the get route that's correct and then in here i mean let's go with authorization of course we're looking for better token and access token and if everything is correct i should see that susan has two jobs one for netflix and one for google and wonderful we have successfully created our application and we have deployed it on heroku as well okay once our app is chilling on a cloud now it's time to set up some nice docs using swagger ui don't get me wrong there are quite a few alternative api documentation options out there but it's hard to compete with a nice end result you get with swagger with that said setting up swagger manually aka writing the code yourself from scratch is no walk in the park it's not that it's hard it's just really tedious and takes somewhat long time and since i don't want to spend three hours on setting up the docs i'll show you a nice shortcut where we can utilize the post mandox and a third-party library to essentially automate the process and as a result save ourselves a ton of time before we continue please let me make it clear this is not going to be tutorial on swagger ui we just want to create working docs and in fact i won't dwell on any of the details if you want to find out more about swagger ui syntax and other options please utilize one of the tons of nice tutorials and blog posts out there and we're going to start our documentation setup with a little detour where i'll show you how to clone an existing heroku app needless to say technically it's optional if you don't want to do that you can just keep using the project we used for deployment but if you're anything like me essentially if possible you don't like keeping the projects on your local machine and instead you want to keep them on a cloud i think you'll find this video useful and i want to start by navigating back to my desktop i'm looking for my terminal first i want to navigate to desktop so let's say here cd desktop then we want to go with heroku so that's the cli then git clone and hyphen a and after that we need to provide the name of that which in my case is jobs api 0 6 so either you can copy and paste or you can type it out and in my case i'm going to go with jobs api and 0 6 and now on my desktop i should have the repo and what that means is that the url is pointing back to the heroku so every time we'll make some change of course we'll push it back to heroku and all the changes will be applied now what's missing of course is the node modules as well as the dot env because remember if we take a look at our git ignore this is not pushed up to the github now in order to fix that we'll need to create a file so go with dot env and then we want to provide all three values uri and rest of the two for djwt now where you can get them we'll remember if we navigate to our application then more specifically settings we have our variables correct config vars so just open this up set it up in dot env install all the packages and then you can run npm start and once i'm done setting up my environment variables like i already mentioned we're gonna go with npm install so install all the packages and then let's go with npm start now since i want to make tiny changes here there's not gonna be that much code essentially i will keep in the package just on node objects please keep in mind that if you want to add more changes to the project it's probably more useful to set up the command where you're using the nodemon because if you remember it's quite annoying would know that you have to restart every time you make the change again we'll have only like i don't know six lines of code so it doesn't really matter in our case but in general if this is what you're doing if you're cloning the app back from the heroku just remember to change the start command or set up some kind of command that you can use in dev where effectively you are using nodemon right from the get go and if i can see that server is listening on port 5000 that means that everything is correct and if i navigate to the localhost 5000 in my browser i should have that silly jobs api and with this in place now we can start setting up the docs once our application is running on localhost 5000 we want to swing back to the postman and we want to get the documentation and the way we do that we look for our collection and before you do anything just make sure that the global url variable is the same in all the requests in my case i'm using the production one but it doesn't really matter since we'll change that value later anyway so you can use the url just make sure that all the requests have the same value otherwise you might get some weird bugs and in fact postman offers documentation itself the problem is that once you publish it it actually goes to a separate url now what do i mean by that well eventually in our api we'll have the route api docs as you can see and this is where the user will be able to access the docs with postman once we publish the docs they're automatically hosted online but on a separate url and since i want my docs to be on the same server that's why we're doing all this swagger stuff and in order to export documentation just look for the collection again jobs api make sure that the urls are all the same in all the requests and then the option you're looking for is this export one if for somewhere reason you don't see it just sign up for a free postman account it's not gonna cost you anything they're not gonna charge your credit card you just need to use the email and you'll be good to go again this is the case if you don't see the export option if you do then smash the export option like there's no tomorrow afterwards pick the second option then decide on the name and location and in my case i'm gonna go with docs json and i'll save it on a desktop and once we navigate to the location and we can see the json file then of course we can move on to the next step awesome once we have the postman json file we are halfway there we just need to fix a tiny issue you see we cannot pass postman docs directly into swagger ui effectively we need to format our data first just so swagger understands what's happening and in order to accomplish that we'll have to sign up for one more free tool api matic important side note just like other course resources it's free and i have no affiliation to them so in order to follow along the videos go to apimatic.io and sign up for free account assuming that you sign up for the account this is going to be your dashboard and you're looking for the import option and we want to import that docs json in my case i'm going to be looking in the desktop and i want to import yes now don't pay attention to those warnings as long as you don't have any errors we should be good to go so i'm going to click on proceed and once you have the api instance in place before we can ship it to swagger ui we'll need to edit a little bit so this is the case where we'll add the proper url we'll set up the proper authorization and all that cool stuff so we want to click here on edit api and let's just start with basic settings and as you can see we have tons and tons of options but totally honestly we'll just go with a bare-bones setup since i don't want to waste too much of your time and as far as the name i think i'm going to go with jobs api if you want you can add the image that's not what i'm looking for so i'll just save basic settings and this is very very important make sure that you save before moving on to the next configuration options then we're looking for server configuration option the environment will be production server name i'll just leave it as server one and when it comes to url this is where you wanna pass the url that points back to your heroku project so in my case let me double check i'm gonna go back to heroku here i have my jobs api open app so that's going to be my route now one downside with heroku is that yes it takes time to spin up that dyno so that's one thing that you need to keep in mind and i'll just take the url i'll navigate back to the api matic copy and paste and then remember as far as our routes we still want to go with api and then version one and then we'll have auth and jobs again make sure make sure make sure make sure that you save the config settings it's very easy to make some changes and then just forget about it and when it comes to authentication yes we'll use the better token so auth 2.0 that stays the same after that we want to move on to the endpoints and here in the endpoints you'll notice that all of them effectively have the authentication and that's not what we want because if you remember as far as our api well these ones the actual auth routes well we don't want to set up the authentication on them correct these are going to be the public ones and only the jobs will be protected and will require that token hopefully we're on the same page we're looking for register user and login user so let me open up this endpoint here then we want to change the group and i'll change it to auth and i want to skip the authentication because by default the authentication is going to be added to all of them so let's save the endpoint and now we should see the auth folder and in there there's going to be a register user and we're skipping authentication this is very very important and the second route that i want to add is the login one so look for the login user and same deal we want to skip the authentication and we want to place it in our auth folder so let's save the endpoint and then for the rest of them we are not skipping the authentication so don't click here but what we want to do is change the folder so for all the routes one by one i'll add group and the name will be jobs and once i say i have jobs folder with create job wrote and i'm not skipping the authentication and essentially what you want to do apply the same group to the rest of the routes get all jobs all the way to delete job and since it's not very useful for you to watch how i do that i'll pause the video and i'll just add this jobs group to the rest of the routes and once i'm done i will resume the video and once you're done you should have two folders the jobs folder with all the jobs routes and again we're not skipping the authentication and auth folder where we are skipping the authentication and we have two following routes register user and login user and if that is the case just navigate back to the dashboard then you're looking for this option you're looking for export api and this is very very very important that you go with open api version three as you can see by default we have version two json you're looking for this one and you wanna go with yaml option so click here and then export documentation and eventually this is what you should see on a screen and if that is the case now we can move on to our next step all right and once our documentation makes sense to swagger ui now let's test it out in their online editor which is a nifty tool that we can use to test out our api docs right in the browser and if necessary apply the changes and as a result save ourselves a ton of time so what i want you to do is go to your search engine and you're looking for swagger error or swagger ui error doesn't really matter and then you can open up two tabs because you'll notice that they do provide some boilerplate code which of course you can use in order to understand the entire setup and this is exactly what i'm going to do so i have one tab open and i'll open up the another one and in there i want to copy and paste this entire thing so let me select it then go back and i want to copy and paste after that we can technically start testing our api but the problem is that we still have the params unfixed and also we have this extra tag and we'll start with the tag where basically navigate to the bottom where you have the tags and just remove the first one so that's done and then let's deal with the query parameters because if you take a look at our project notice we have jobs and then for single job the update job and delete job these are query parameters but at the moment everything is hard coded so how we can set it up in swagger z params well we'll use their docs this is going to be the case where i want you to again use your search engine and just type swagger ui parameters a quick side note if you can't be bothered going through the swagger docs you can always find the correct code in the project readme you're looking probably for the first link then we'll keep on scrolling yep all the details and all that but what we're interested is common parameters for all methods of the path now i don't want you to take the path part but i want you to take everything starting with the user all the way to get so take this code yes we'll modify but this is just going to be faster if we set it up this way go back to your error and what you're looking for are those single routes so go up here where you have the patch remove the hard-coded one including the column this is very very important and the same for get and once you remove the get part just copy and paste this one in this case we don't want to use the user because the route is jobs correct then we have the id yeah that still stays the same and instead of integer this is going to be a string it's going to be required and it's going to be a job id again if you want to find more info please just read their documentation but essentially what we did right now we added that id parameter in all these three routes get single job update job and delete job and once we have this in place now we can start testing our api and i'll start by registering the user now i'm not going to try out all the routes but i think i'm just going to go with a register and maybe i'll try to create a job and then take a look at a single job just so you can see that everything works and the way we do that in a swagger we look for try it out here notice these are the values that we're sending and of course once you already register user you'll have to change these values around but in my case i deleted the bob from my database so i can execute notice this is going to be the sample request this is going to be the url and voila this is the response so that's my token but the deal again in here is that these ones are protected so if i'll just try to access the job or create job or whatever i'm not going to be able to do that so you want to copy the token and you have two options either you can set up in one of them and automatically it's going to be added to all of them or you can just scroll up and same deal just copy and paste the value authorized so now i set up my token so i can close the register i'm good to go now we just want to create a job so let's go to the post request again we're trying it out i'm going to go with the same google and the front-end developer we'll execute we should get back the job the 201 and now if i go to get all jobs and we try it out we just execute we don't need to provide anything we have our jobs array with a counter one and if i want to take a look at single job we want to copy and paste the value and as far as the setup either of these is going to work so either get patch or delete and my case i think i'm going to go with get we want to try it out again after that we want to paste the job id remember as far as the authorization we right away set up the token at the very very start so now of course we're authorized to make these requests so once we execute check it out now i can see my one job and once everything is working now the last step is just setting this up in our application so we'll still need this code so don't remove it or mess it up but the good news is that we're pretty much done with the hardest part so i promise it's going to be a smooth sailing from here on out beautiful and once we have tested our api in a swagger editor now we just want to add it to our application and in order to do that we'll need two packages we'll need yaml js and the swagger ui express now if you can see both packages in the package.json then of course you're good to go but since i added these packages later essentially they were not with initial star you might need to install them yourself so if you don't see them just run the command of npm and i or installed doesn't really matter then go for yaml js and swagger ui ui and express so this one will convert the yaml one to something that the swagger ui can understand and swagger ui express just adds swagger to our application so i'll install both packages even though i have them and i'll start by creating a new file and in my case i'm going to call this swagger and yaml now the name is really up to you just make sure that the extension is yaml and now you want to take this entire thing again this is a little bit different than what we have from api matic this is already a working documentation copy and paste and back in our app.js we want to do two things we want to require the swagger ui express the yaml js and then load the yaml file and then we want to pass it on to the swagger ui so i'm gonna go below the extra packages we'll add comment here i'll say swagger and let's just start by grabbing the swagger ui again we're just coming up with some kind of name and this will be equal to require then we're looking for the swagger ui express and since i have yaml file i also want to do that and that will be equal to require and we're looking for the package and then we want to load the file so in here let's just come up with some kind of name i'm going to go with swagger document and that will be equal to yaml that's the variable then dot and the method you're looking for is load and in here you want to point to the file which of course is in the root so we simply go with swagger dot and yaml and once we have all of this code in place now we just want to scroll down and where we have here the app.get above it below it it's really up to you we'll go with app.use then we need to come up with a path and in my case i'm going to go with forward slash api docs and you know what actually changed my mind i'll place it after the forward slash so let's go here let's say api docs as you can see we're using app.use so it will be a middleware and then as far as the code we want to go with swagger so that's our variable and we're looking for the serve property and then we want to get that yaml file so again we go with swagger ui setup method and in this case we want to pass in that swagger document once all of this is in place now i just want to go to app.get and instead of sending back jobs api what i want to do is send back the heading 1 let's say jobs api i'll close the heading 1 and then i'll just set up some link that goes to api and for some reason i went with api use should be api docs my apologies so let me go here i'm going to go with href and we're going to set it up as forward slash api docs and then let's close the link and let's just say documentation and once we have all of this in place now let's run npm start but i can tell you right away that if you'll try to test this on a local machine it's not going to work basically you'll get a bunch of errors so everything is going to work once we push this up to the get up for now i just want to see whether the basic setup work so let me look for localhost and then i'm looking for 5000 i should see the documentation and once we navigate here voila we have our documentation in place now the only thing we need to do is just go back and then add those three commands we want to look for git add so this is going to add to the staging area then we'll go with git commit let's just say swagger docs added and lastly remember the command get push heroku main or master so in my case it's master now we're pushing everything to the heroku and if there are no weird bugs we should be in good place and the nice swagger door condition should be added to our project and to answer your question yes when you are setting up manually basically when you're typing this yourself you do need to provide all these properties and i just thought that it's much easier to show you how to do that automatically because you need to keep in mind that as we're progressing with the course our projects are going to get more complex and i really don't want to spend five hours on a project and then another five on the documentation because it seems like a big waste of your time so now let me navigate back to my web browser i'll close all of my tabs since i have 10 000 of them open i want to go to heroku i want to open up the app i have my documentation awesome and now let's test it out so before we do anything why don't we remove that bob user because i think that that way i don't have to waste too much time on changing the values i'm not going to test every route but i want to test out the major ones so let me delete the user just so i can see that everything works we're looking for a register user option i want to go with try it out of course and we want to execute we should get back the token which is just awesome now let's quickly authorize the route so let's add here copy and paste authorized we'll close it and then let's create a job so let's go here we're going to go with tryout and we'll execute yep we're creating a job and lastly let's just get all the jobs try it out and execute i can see that i have my jobs array with a counter one so that's how we can add swagger ui documentation to our api without typing any of the code ourselves
Info
Channel: freeCodeCamp.org
Views: 201,075
Rating: undefined out of 5
Keywords:
Id: qwfE7fSVaZM
Channel Id: undefined
Length: 600min 7sec (36007 seconds)
Published: Thu Oct 14 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.