Passport Authentication w/ React & Node.js + Typescript

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's going on so today we're going to be using react and node.js to build a full website with passport authentication multiple pages conditional rendering on the client side and protected apis on the server side we're going to be building the entire project in typescript so if you are new to typescript this is going to be a perfect introduction for you it is fairly simple in this video we'll show you that so i'm going to be using as modern and up-to-date libraries as i can so this video is applicable for as long as as long as possible i'm going to be trying to go a bit slow for the new programmers out there because i felt that my previous video on passport authentication was best responded by new beginners programming so if you're an experienced programmer go ahead and speed the video up because i'm going to truly be taking my time to explain everything i possibly can so that nothing at all is confusing and yeah so if you enjoy the video please leave a like because i personally could not find a video like this and i had to use trial and error to find out how to do um this method so hopefully this video is out there and you guys don't have to use trial and error and this video can be a great introduction for you i was going to actually implement some of the oauth strategies such as like google or twitter or something like that but these are fairly simple strategies to do they're no more difficult than what we're doing and i felt that i was already doing so much within my time that i have for this video that i'll probably just include oauth in a different separate video because passport is an awesome library and i really believe a bunch of videos can be made on it because um it's one of the most useful libraries i've ever found so if you want to see that video just go ahead and let me know but this video is going to be more centralized around what i've talked about previously over in visual studio code you can see that i've opened up a new folder in my desktop passport react video full so to do this project i'm going to create a folder for the back end and a folder for the front end so i'm going to go ahead and make the folder for the back end i'm going to cd into the back end and i'm going to initialize the folder by running npm init dash y i appended the dash y flag to it because i don't want to type in all of the fields manually i just want them filled out for me so now we need to install a ton of dependencies so i'm going to go ahead and just install them and i'll explain what they do afterwards so here i've installed bcrypt.js for our uh password hashing i have cookie parser so that we can read and parse the cookies that are in the um back end and client and i have cores here so that we can access this our server for multiple different origins or we can specify the origin so that there's no security error i have dot e and v here so that we can read environment variables that we input into our application such as secrets that we want to store and we don't want anyone else to see i have express here which is our main library for our server i've expressed sessions so that we can store sessions inside of express and authenticate users i have mongoose here which is our database and i have passport which is our authentication library i have passport local which is our library for passport our authentication method so now that that's done i'm going to go ahead and start up the client over here where we're going to install a react app so i'm going back into the main folder and i'm going to start or create the react application by running npx create react app and to specify that this is a typescript application when we want to install a typescript template we'll use dash dash template typescript and then we write the name of the folder which i want the name to be client because it just makes sense now inside of our back end which is this terminal over here we're going to actually want to install some dev dependencies so that these libraries are compatible with typescript so here i'm going to just go ahead and install all of the dev dependencies for these libraries so if you take a look here i've been i've typed all of the names of the libraries but i prepared them with at types slash so this is basically a separate npm module and it's all of the types for our library so bcrypt has a bunch of types for typescript which include auto completion interfaces etc and you're really going to see what these do as we build the project because we're able to read so much more about the modules and what they do and um auto completion inside of them if we add these libraries to them so here's all of the names of our libraries with the at types perpended to them and make sure at the end that you add a dash d flag because these are dev dependencies we're only using these as we develop inside of our production code we do not want these installed because our production code will always be compiled to javascript and we won't need anything typescript related inside of our production code so make sure you add d to the end of that now that that's finished we have a few more dev dependency dev dependencies to install one of them is going to be nodemon another is going to be ts dash node so that we can compile the typescript and the other one is going to be typescript so all of these will make our project i'm sorry the two of these will make a project for typescripts and this one is just so that we can run our server without restarting it manually each time so with all of this completed you should have this full package.json which is going to be the bare bones of what what we want to do inside of this application so these are awesome libraries they're not going to be updated anytime soon i do not believe um but yeah we can go ahead and start coding the project now um i'll just go ahead and wait for this to install on the right side and we'll start with the backend folder first so i closed over the terminal on the right side and what we want to do in the back end is create a file called tsconfig.json now what this file does is um you can specify all the different stuff that you want to do with the typescript code and what the typescript code should check for so that you can make it strict not strict etc it's a really awesome it's a really awesome config file so i've actually already written a ts config that i'm going to copy and paste over and you're going to be able to get this same code over on my github page where this project is going to be hosted so check the description and you'll see the link to this ts config so this is good to go you can go ahead and save it and what we want to do now is create a file for index.js which is pretty much just going to be the root of our project i accidentally said js i meant to say ts so index.ts now that i've created a fold file i want to go ahead and make an src folder and i'm going to move my index.ts file inside of it okay now i'm going to create a start script so we can actually start the typescript code so it this start script is going to go as follows i'm going to type in nodemon because i want nodemon to be running this i'm going to type in that dash dash x execute command so it's going to execute the script i'm going to run the ts node compiler for the file src index.ts which will be our entry point so this is our entry point file so everything we type in here will run so as you can see this is going to run hello world cool so let's begin coding inside of our typescript file i'm going to go ahead and put all of my imports here over at the top as you can see these are all the packages that we've previously installed and if we didn't install the types earlier over here we'd be getting an error but we're not so as you can see nice thing about typescript is we can use import statements now instead of the really ugly way of doing it so now that that's finished let's go ahead and let's connect to mongodb first thing so go ahead and login to mongodb.com and create a new cluster if you haven't already and once you've created it come over here to the cluster and press connect connect your application and make sure that the drivers node.js version 3.6 later whichever one is the current and just go ahead and copy the connection string let's run the method stock nights let's paste our connection string and let's go ahead and change this field of password to the password that we're using which in this case is just admin now that that's finished let's make the second parameter a configuration object inside of this configuration object the cool thing about typescript is if you press ctrl space you can see all of the different options that this configuration object takes and if it has a question mark it means it is optional so all of these are optional configurations the ones that we're going to want to use is the use create index use new url parser and use unified typology the reason why is because currently you get an error if you do not use these so we have to use these just to avoid that stupid error so now that that's finished if you go ahead and take a look here we get a callback so take a look at the auto completion here so we have the connection string and the options which is configuration object and we have a callback as another parameter so this callback returns an error which is a type of error i'm sorry it takes a error as a parameter and it returns a promise so pretty cool stuff here as you can see we have an error like it said if there is an error president present then it is going to be of the type error it's just like this just put an error and import it from our library control space auto import and take a look here so we've imported this error type interface so if you don't know simple typescript just take a little video on it it's very simple so if there's an error let's throw it so yeah that'll connect us over to mongoose so now we're connected and we can actually check if we're connected by saying i'm putting an else statement by on some log very good spelling here okay cool so what we're going to see here is that we are connected to there we go so everything's working just fine in order to shorten the length of the video i'm going to be going and copying and pasting the code that we're going to be using for our middleware section so this is simple stuff we're initializing our express application and then we're just calling all of our middleware to instantiate it so we're calling express.json so that we can read the requests that we get sent we're initializing cores and we're passing a configuration object to it with these following key values and we're initializing the session package and we're passing a configuration object to that where we're setting the secret resave to true save uninitialize to true and these are just the settings we're going to be using for our passport application also initializing cookie parser passport and passport session so that's going to pretty much be it for the middleware in terms of that so what i'm going to be doing now is i'm going to be creating a file so that we can create the model inside of mongoose for our user that we want so we'll just create a file called user ts as we did in our previous video and we're just going to create our schema so we're just calling the schema function here and we're passing it a configuration object and for a username field we wanted to have a value of this object here where we can pass in multiple settings previously we just did string and then we moved on or i'm sorry like this but in this video we're going to be making our username a bit better by adding an object to it so we can specify multiple settings and not just string so we can do whatever we want we can have a ton of different options here so if you do control space you can see all of the stuff that we can put in here but i'm just going to go ahead and put one other thing which is going to be unique which means that no other user can share the same username inside of the database make sure the password is a string and we're going to be creating another field called is admin and this is going to be a boolean whether it's true or false and the default is going to be false okay so these are pretty much our our schema settings over in the mongoose library okay so these are our schema settings here now let's go ahead and just write export default so the first parameter is going to be what do you want the name of the model to be and the second parameter is what is the model actually so this is the name of our i think our collection and this is what the collection is defined as so cool now let's go and import that over here i'm going to go ahead and start by creating the route here to register so the route to register is pretty simple okay so as you can see here it's the same as the video we did before it's just going to be a post directory so somebody is going to post to the route dash register and it's going to take a request and response now because we're using typescript we can technically define the interface for request and the interface for response if we want to oops if we want to and these should be imported from express so we could do it like this and but i really don't see the point in this because we're not constantly redefining requests and response so leaving them as inferred types is totally fine too so i'll probably just put it like this just for the sake that we're using typescript and we want to feel edgy so i'm going to go ahead and create a variable and i'm going to call it hashed password and it is going to be bcrypt.hash and check out the autocompletion up here the first parameter is a string to hash well we want to hash the request.body.password that we're going to get from the request and we want to salt it with 10 which is the salt length or the strength all right so this is a weight so we're going to make this an async function cool um now we have to do is we are going to make a new user like this um okay new user and let's pass in uh the username as request.username password is the password okay and this new user has already been defined over here in our schema so i'm saying new user meaning a new schema et cetera et cetera and i'm not going to pass in the is admin because i set it to default as false so it'll fill that out for me automatically so then all i have to do is just await this new user and run the save method on it so that'll save it to mongodb and then we can send um success to it cool so this will actually register us as long as we provide a username and password inside of our request that we send it so i'm going to test this out with postman okay so now that we're over here in postman if you've never used postman before it's pretty much a tool for whacking endpoints and building up building services by whacking an endpoint and seeing what happens so right now we're going to send a post request to localhost 4000 slash register now um i actually forgot to um to start my app so let's do that okay now we're running an application on port 4000 so now we can go ahead and save that and it should say server started and see the route here is dash register so let's go to locals 4000 slash register post request and let's pass a body to it of username one two three and a password of one two three but actually i want to make mine um one two three four one two three four five i don't know why okay there we go so you're going to see success and if you check mongodb you're going to see that the user has been created okay so over in mangadb if you actually go into your cluster and you click on collections you can see that it generated us a username of one two three four five and a hashed password which we know is one two three four five and an is admin key object okay so now that that's finished let's go ahead and let's put some validation on this endpoint so that people can't just troll us and put in whatever they want into the register and expect it to work okay so we're actually going to want to destructure the password and the username off of the request.body object and if you don't know what destructuring is you could just i don't know check out a video on it it's a pretty simple thing okay so let's make a conditional statement that says if the username of the password doesn't exist or it's not a string then we're not going to accept it okay so we're just going to want to send okay and we'll just return here if it hasn't already returned okay cool now that that's done we are pretty much gonna have some validation here for our endpoint but the problem is if there's no request.body we're going to get an error when we try and destructure the username and password from it check it out if i just send an empty post request we're going to pretty much crash the server and it's going to tell me that we can't destructure a value undefined whatever so to fix this just put a question mark after request meaning if there's no request then just return undefined so go ahead and save that and try it again and it should just return improper values like that perfect okay now let's go ahead and clean up our code by just removing the request out bonnie off of here and because this is a duplicate we can just erase the latter part now let's go and check the database if a user already exists if the user already exists let's just return that it already exists and if there's no document well then we want to create a document here so all of this code is going to be what we're going to use and this should successfully register us without having any uh any problems so now what i want to do is i actually want to create an interface so interfaces in typescript is a file in which you can define what an object has in specific so you can specify what the keys and what the values types are so my interface is going to be for user and you can name it whatever you want but i'm just going to name my user interface because it makes sense and user interface is defined as having a username password and an is admin so now that we've defined the user interface we can come back over here and we can plug him in as a document interface so um the document that we get back from is going to be of the type user interface because the document has all of these key values on it so hopefully that makes sense if not just take the time to think about it okay so now that our register is done let's move on to the passport stuff because now we can register users non-stop i already made a previous video about passport but i'm going to go ahead and put the passport code inside of here right under the initialize and right under the session middleware that we added okay and we're going to define a new local strategy for passport to use so i need to create a variable up at the top that's going to just say let's use a local strategy from this library so we can do so like this const local strategy that's just what we're going to call it we can call it whatever is going to be equal to passport local and let's call the strategy class from it i think it's i'm not sure if it's a class yeah it's a class that was a good guess okay so let's go ahead and let's start defining it okay so i'm going to go ahead and just paste the code over because i already made a video about passport and how it works in my previous one and i don't want to spend too much time here so i'm just going to go ahead and paste the code from the previous video you can find this code on github if you'd like but i already explained how passport works but you can look up the simple basics here we're defining a local strategy and we're performing some validation that says um let's compare the passwords if they're true then let's just return that it's successful pass the user with it we have serialized and deserialize and this is how it interacts with your cookies in your browser i made a video on this but you could totally just look it up on stack overflow or something i don't want to spend too much time on it so now that passport is set up we can register and pretty soon we'll be able to log people in we just have to build a route for the login so the route to login is going to be very very simple it's going to be a lot more simple than the previous video i made because i found an easier way to do it okay so this was in three lines what i did in the previous video took forever and it's really easy to just pass the local authentication method over as middleware before we get to the function so what the passport dot authenticate method does if you check out in mozilla is it authenticates the user by calling request.log in so we could specify a ton of different options if we wanted to but this is just a simpler way of doing what i did in the previous video yeah so this is pretty much what i wrote in the previous video but now we're writing it much more simple so now that that's done we can go over to building the get route to get the user that's currently logged in okay cool so now that that's done we can see what the current user logged in is so this is all the code that you need over on the server side to authenticate users okay so now that the server side is done let's move over to react and let's install the dependencies so the dependencies i need to install are axios and react router dom now the reason that we need react router dom is because we're working with multiple components here and we want to route between them as if it's a normal web page so react solution is the module react router dom and you'll see what it does later if you haven't already axios is going to be our http client so that we can send requests on a very simple basis okay so now let's go ahead and let's perform a cleanup here i'm going to go ahead and remove all of these css files i'm going to remove the test file as well the logo all of the stuff that i don't need which is almost everything okay now let's clean these files up let's just make this return an empty div okay so i'm going to build out my folder structure over here i'm going to create a folder for the pages and a folder for the components like so the component that i want to create is going to be the nav bar and typescript react files are defined as dot tsx now the pages that i want to create are going to be the admin page to check um or just a certain page that only administrators can see okay so i've created all of these pages i'm going to initialize them with my react extension tool which is let's see i have a tool called react snippets that i installed and if you install it too you can get these cool snippets so you can start off really really easy functional components with rfc press enter and you get the navbar i'm going to initialize all of my components like that okay now that that's finished we can go ahead and station the nav bar in here all right and i'll import that and we're going to be using react router dom now so that we can route between all of our different pages and the browser router is going to be the main container for all of our routes you'll often see a lot of people import browser router as react router dom but i just don't really see the point in that so i'm just going to do browser router as so now it's going to tell me that it wants me to have a container for all of my files so i'm just going to throw the nav bar inside of the browser router i'm going to create a switch statement now and the switch statement is imported from react router dom and now that that's done we can go ahead and start defining our routes inside of my switch statement i am going to just paste some code and put some imports up here and now i have to import all my components okay so these routes are pretty much defining that on the path of just backslash which is the home page i want the component to be the home page so i want to display the homepage on the slash path which is the homepage on the slash path admin i want to display the admin page on the path of login the login page in the profile the profile component cool so hopefully all this makes sense so far too now let's go ahead and define our navbar so that we can actually cycle between the different pages so currently if we actually run our code we're going to be getting an error and it's because we don't have any types of the library react router dom so because we're using typescript we're going to have to install those types so install at type slash react router dom as a development dependency so that's going to install and we won't see an error anymore up at the top and we can compile our code now i went ahead and i added some things to our admin page home page login whatever so that we can differentiate from them as we start our application i just want to show you that they're the different pages so currently on our path if we go to slash we're going to get home page admin admin page so let's actually view this in action before we move on to creating our nav bar okay so if we just go to local 3000 that's our homepage our login page that is our admin page cool so everything is working as expected let's go ahead and let's actually build an app bar now so that we can switch between these pages seamlessly so inside of our navbar we're going to create a main div and let's just call it a nav container now we can do this many ways we can use css modules so that we import the css module instead but for the purpose and sake of this video i'm just going to give it a generic class name of nav container and if we wanted to build a full application i would recommend css modules instead but now that that's defined let's go ahead and let's start putting our links in here so that we can cycle between different pages okay so i'm actually going to add a ton of links here instead of just the ones that i've already created and let's see so okay so i have a bunch of links here i have one for log out home profile admin and we haven't created a logout yet but we will so no worries now over here i'm going to create a few more i'm going to create login home and register so i'm using the links from react router dom so that when we click on them it takes us to these routes so if we click on this object in our browser we'll be taken to that route you'll see what it is in a little bit later now let's go ahead and let's style this so that we can see all of our different links in our navbar okay so i'm going to create a new css file here and i accidentally made it outside of the directory let me move it into the src folder okay main.css and all i'm going to throw in there is just the style for the nav container which is just a width of the entire screen height of 100 pixels background of black all the color of the elements to be white display of flex align things in the center along the vertical axis and space everything out horizontally so let's import the main css into our file like so and i meant to do it like this okay now we should see it over in the browser okay and we do indeed we see all of our links and if we click on them it takes us to the different routes you can see the url here clicking on this takes us to log out home profile admin login home and register now currently we only have the components defined for profile for admin for login and for home we haven't defined any for the register or log out and stuff but we'll have to create those pretty soon here okay so real quick what i want to do inside of my main css is remove all of the default styling from our elements and that will get rid of this weird gap you see over here now the gap is closed and our styles are normal because i've removed all of the default styling that's applied to every um html element now that we've built up the nav bar let's make a way for people to actually log in and so that we can see that our login method is actually working so what i'm going to do is just start off by a div create a tag to log in now i need to make some state to hold our username and password inputs i'm going to define here that the input type is required to be a string okay and now i'm going to call this set method and set it to whatever the client is having typed into its inputs i'm going to create a function that actually handles a login and creates a request over it i'm going to call the axios library but first have to import it and now i'm going to pass in the data that i want to call with it oops and i can type in the configuration object with credentials true okay and then once it's logged in i'm going to just make a promise and i'm just going to log out whatever the promise says on the response okay and now let's make a function to get the user that's currently logged in and over here in the index remember we have a route or user and the route returns whatever the currently logged in user is request.user is the user that's stored inside of express session that was put there by uh passport.js so we should see it one very very important thing that i forgot to put inside of the login is oh i did with credentials true sorry if you do not add this your entire code will break cool so now we can test it out oh i'm so sorry um i've actually written this wrong so what needs to go here in the configuration object is the data that we're passing okay so we're passing a we're passing the username as the key of username but because of duplicate values we can just remove it so we're passing the username and password over to the login function okay now we're gonna do with credentials so one problem with recording something live is that you make mistakes like that but here's how the code should really look so now let's try it out okay now let's go ahead and okay and you should see successfully authenticated if you registered a user by one two three one two three which we did earlier in postman here okay and now let's call get user that's currently logged in and let's see we're not getting any response let's check out what's going on over here oh i'm i can't believe i did that so i actually forgot to attach the function to the button okay now that the function is attached we can call getuser that's currently logged in so log in successfully authenticated and we get back the that we are logged in so if we refresh we change tabs we do whatever that user will always be logged in because we've created a session inside of express which is our server and it persists across our url or i'm sorry our origin so if we win incognito then we wouldn't be able to see who's logged in because it's a different session but during this session we're always going to receive this user back so now that that's finished how do we pass this context to all of our different components to pass value to multiple components we're going to be using something called context by react which is a hook context provides a way to pass data through the component tree without having to pass props down manually at every level you can read through all of the documentation here but i'm going to go ahead and just start creating it i'm going to create a file you can name it whatever you want i'm going to make my file name context now i'm going to generate the component with rfc and up here at the top i'm going to create a variable and i'm going to name it whatever i want but in this case i'll call it my context now i want to call the create context hook to create some context now inside right before the parentheses we can define its type i want the type of it to be anything you can define the type that you want but in this case i don't want to make the tutorial too long so i'll make it any so over here in the div tab or div tag let's just remove it and instead let's put the my context variable i've just created now inside of here put dot provider because it is going to be a provider you can read more about this if you like it's about react providers so then enter for the value whatever value we place here will be the value of the context now inside of the component up here i'm going to get the props which are going to be of type any but i think that you can do the props interface which is deprecated props to children okay cool and i'm going to pass any to it now over here we're going to do props dot children for the um for the value of it now what this is going to be is this is going to be a provider to all of our other components for the value of 1000 and it's going to pass all of the values through it it's a little complex but if you can become comfortable with this then you can understand everything about react that's complex so just please become comfortable with this now let's move on to actually putting the provider inside so we're going to want to do that in the app so inside of the switch statement let's put the actually let's put the provider right where the browser router is so we're going to do is we're going to do the context component and it's going to wrap everything so now everything has that context available to it which is really neat okay so now to actually use the context that we defined remember we define the context as being 1000 we can enter component and call the use context hook so if we go into one of our pages for example i'm going to go into my home page to use this context what we do is we create a new variable distorted i'm just going to call mine ctx and it's going to be attached to the use context hook and this use context hook is going to take the the variable we exported over in the context so right here my context so i'll paste that in and then import it so now let's just console.log ctx and we should see the value that's being passed through it which is this one 1000. so let's head over to the home page okay and let's go to home okay and we're not seeing anything and the reason for it is is because over in the navbar home is actually just slash as we've defined it over here as slash so the navbar shows slash is home so now when we click home we should just see slash as home page now if you check the console we see our value printed out as one 1000. so let's actually go to the context and let's put some meaningful state here i'm going to put a used use effect hook and this use effect hook is going to render on every state change i'm going to make an empty dependency array okay and inside of here i'm going to make axios call the get user route or endpoint and we're going to save whatever the currently logged in user is and make that our context value we're going to return a promise and now we have this we have the user stored in the res.data let me go ahead and make some state here and let's store the user inside of this use statehook okay now when we uh call this request here we're going to have the user come back as res.data and we're going to store it inside a set user so user now has the user inside of it so let's pass that value here so now it's going to be calling this this um endpoint setting the state and then passing that as the value for our context so now if we go back to the home page we're going to see the user that's logged in as the context so now we can virtually access this variable from any component so i'm going to go to the nav bar and actually use it so again let's create a variable i'm going to name it context can name it whatever it's going to be use context and let's pass it the my context now we have the user inside of the context so i'm going to make some conditional routes so for example if a user is logged in then i do not want to show the login page or the register page and vice versa if the user is not logged in there's no reason to have the logout route there's no reason to have the profile and there's no reason to have the admin route so let's go ahead and separate our routes so if the user exists then we want to return let's see we want to return log out for sure we want let's see we want admin oh but see we're actually going to also need this conditional rendering as well because admin is going to be a specific route only given to administrators but we'll deal with that later so we also are going to need the let's say profile so these three routes will render if there's context if there's no context then we're going to render these routes and i accidentally closed this a little early so let me move it down here so hopefully at this point your code should look like this now it's going to complain that we need to have a parent or i'm sorry a wrapper and we can do this by just making these empty tags here which are called react fragments like so so now let's see if we can format this a little bit better okay that's good enough so now we're conditionally rendering if there's context so if there's a user logged in we're displaying log out admin and profile if there is no user logged in then we're displaying login home register and this one is going to apply to both so we're going to leave this out so let's come out of our loop let's just slap this thing outside of it so in either case we still have the home page so now what you're going to see is because we're logged in we have log out admin profile and home so if we log out which we haven't implemented the ability to in the server side let's see i think i just have to restart my server yeah if we restart our server it's going to kill all of the sessions that are logged in so now we're logged out you're going to see these routes home register oops we have home twice so sorry let's get rid of that and now you can see we have login register if there's no context if there's context we have log out admin profile hopefully everything makes sense if not pause and take the time to look it over so now at this point that we have our contacts done we also want to conditionally render if a user is logged in we want to see if they're an admin and if they are an admin then we want to display this route as well at the top if they're not an admin then we don't want that route so check check it out i'm going to log in notice i'm going to just have to refresh the page and we have admin up here i'm going to now make a conditional statement that says context dot and i'm going to do is admin and if you are an admin then let's return the admin link if you're not an admin we will just return null so let me paste this inside okay cool all right so in this case because i'm not an admin i'm unable to see the admin panel one of the things i notice when building the nav bar is that i actually forgot to create the component or register so let's create that component now okay now let's plug the component in so that we can render it on the path of dash register we can pick whatever path we want but i just feel like it makes more sense in this way okay we could put like i said whatever path we want on the server but we're just going to keep it at register so now we have the register page created so now over here in mozilla you can see that our register page is connected to register see the route we're on is dash register okay now that we've created the register page what i want to do is i want to do what we did for our nav bar but do it for our actual routes so let me show you what i'm talking about if i'm not logged in i can still visit the admin panel and it displays admin i don't want to show anyone the admin panel unless they are logged in and unless they have the is admin flag so let's conditionally render everything let's paste our context value from the navbar over into the app okay and let's just import now that we've imported it we have access to the context so let's write some conditional statements if a user is logged in then he should be able to visit the admin page he should be able to visit the profile page and if a user is not logged in meaning there's no context then we want to display the login page and the register page oops wow sorry about that i'm just having some trouble okay there we go okay and regardless of what the context is unconditionally we still want to have the home page here now we also want to make the admin page conditionally only render if the user is an admin so we'll write another conditional statement inside of our already previously existing conditional statement if the ctx dot is admin is true then we want to display this component and if he is not an admin then we'll just display null okay and now i'll just format it a little bit better and there you go so if we actually run this code we're going to get an error and i wanted to make a learning experience out of this because it's an awesome way to show how the context works so i just want to show you real quick let's console log our context here now we've done this in an earlier component earlier in the video i mean and we see that the context has a stateful value inside of it but we're not going to see anything in fact we're just going to see the empty object meaning that it's completely empty and the reason for that is that this context here is where we're actually getting the stateful value from and if we don't have a context wrapping the component we're calling it from then we're not going to receive anything in return so what we can do is just remove this context components here and we can go back into the index here and just put the context there okay and now if we go back into our app this same log statement here is going to appear as in undefined and in this case it means that in our context here it's returning the undefined that we put into our state which is the value so if we log in again we refresh we're going to see the staple value so that's how to call the context correctly now all of our rendering is going to work perfectly we just have to move this over here above the conditional statements so that we're rendering the path despite any conditions so now we're conditionally rendering our entire application that we're using so far so now that we're conditionally rendering a react app i want to go into the server side and create a route so that people can actually log out and it's pretty simple to do this in fact if you just look up here passport logout you're going to find some seriously simple documentation on building a route to log a user out now all we have to do is just define the route and as it's showing here there's a log out function that's on the request object that they've added and all we have to do is call it and it removes the user property and clears the login session if there's any so all we have to do is just call request.logout and i'm just going to send back to the client or whoever called it that it's completed so that this way once it's done being logged out we receive success so now we're able to register users to a database we're able to log users in and authenticate them by calling the passport.authenticate method and passing the local strategy to it which we defined here as a local strategy now we're able to grab users and receive the currently logged user in currently logged in user sorry and now we can log users out just like so all you have to do now is just go back over to the nav bar and just create a really simple function to call this logout route that's in the back end and i'm going to pass the with credentials configuration to it as well and that just means that they're able to read the cookies that's in your browser and the cookie in your browser is what passport is actually using when it serializes you which i think i explained in the previous video but the cookie is this value and when we want to pass this cookie to the back end which is being created and handled by our passport we have to pass the with credentials configuration object to our request and the backend is able to receive it so make sure you add with credentials to all of your calls so that the back end can read the cookie and which user is trying to make the request i'm going to attach a promise to this call so that when it's completed we can do something i'm going to just console.log whatever the response is that's coming back and now i need to attach the logout to an onclickeventlistener to this link that we're rendering so now if i go back over and i login and i refresh you can see that the logout button is here let's go ahead and click on it and if we read the console this is what we're receiving back we are receiving data as success which is correct that's what we're sending and a status of 200. if i refresh you can see that we are logged out and we're receiving the nav bar for someone who's logged out so now what i want to do is actually reroute a person once they've logged out successfully and we can do so like this i'm going to say if the response says success which it does because we've defined it right here you can honestly say whatever you want but in my scenario i'm going to say if the response says success i mean you could do if the response dot status is 200 or whatever you want i'm just going to say if the data that comes back says success we want to redirect now because we're using react router we could use the history which comes with react router which is how we handle history between different pages but because we're not using history because i want to make this video as centralized around logging in and authentication as possible i'm going to use a different method so that we can reroute users very simply i'm just going to add a assignment here that changes the window.location.hyperreference to the home page now this will just redirect us to the home page so let's try it out refresh and now when i click it we get redirected to the home page and we're logged out i also in the login page want to redirect probably to the home page as well so on the login let's see what we're being sent were being sent successfully authenticated i'm going to use i'm going to change this to success just because i feel like it's a really easy string and it's consistent and i'm just going to say let's redirect to the home page now cool now we're redirecting as well when we log in so as well as i'm also going to remove this get user because we're no longer needing to actually get the user that's logged in because we have it in the context so now that that's completed i'm going to get rid of these errors here cool so now we're able to log users in and it's going to redirect us and we're able to log users out and it's going to read rectus cool so the next thing i want to do is probably get rid of this styling and then continue forward with the project so fixing our styling problem is actually extremely simple this color here is not being is not working as i expected because we need to style the elements that are actually inside of this container now these link elements are anchor tags as you can see here so we need to style is the anchor tags inside of the nav container and we can do it like this i'm also going to remove the underline cool so the next thing i want to do is actually handle the administration aspect currently what's going on is that we do not have any users that are administrators and we see this because our users inside of our database all have the is admin flag set to false and we can visualize this inside of mongodb here if we go over to our collections to see all the users inside of the database the is admin flag is hit to false now you can build a route to change these to be true and you can do a million other things but for the purposes of this video and to make the length a little bit shorter i'm just going to be manually changing the is admin to true i really hope that this isn't a problem and that you guys are able to create a route to change the is admin to true such as creating a route where somebody can post to and change this flag to true or something but for this scenario all i want to do is i just want to manually change some of these to true so that we can get some conditional rendering on the admin page where currently no one can access because nobody is in admin as you see here so let's manually make some entries to the is admin page i'm just going to go to my routes and change the is admin in the register to true that way it registers a user and it makes is admin true now i'm going to build out some users that i want to make administrators i'm just going to make a username of nate password of one two three and let's see oops no user exists by that so i guess we have to build a register form so i can probably copy the code from over here to my register page very simply and then change everything around and i should be fine now as you can see all that we have to change is just the log in over to register and i believe that's all we need so now if i go to the register page i'm able to register some new users hopefully nate123 let's try it out i'm also going to add a very simple redirect here and i just noticed that on the register i'm sending back success in upper with an uppercase s i'm going to make it lowercase s just to be consistent with what we're doing in the rest of our application so if it's success i want to redirect to the login page that way when a user registers it can immediately log in now if i log in here because i am an admin as i defined see his admin is set to true now i have access to the admin page which i previously didn't so i'm going to make some cool just a very strange random maybe json dump of data that only administrators can see for the purpose of conditional rendering so let's build a protected route over on the server side so all i have to do is just start off with a get request and i'll return all the users that are in the database or something so hopefully this should work i'm actually just gonna throw an error instead which you shouldn't do but i'm just doing for the purposes of the video okay so let's try this out notice how every time i save the server it ends all of the sessions and logs everybody out that's logged in and the reason for that is is it's deleting the in-memory storage of these sessions so this little fyab now i guess we'll use postman to check on this so i i also just realized that i'm assigning a variable and i don't want to do that so i'm just going to remove that here so let's open up postman and try this out so now if i submit the request we get back all of the users that are logged in which really for the purposes of this video is good enough for i don't know just some sensitive data that we only want administrators to see we could allow administrators to change all of this data to delete users but i think in this video we will delete users uh i'm guessing so what i want to do is come back here and make a request to delete a certain user and then what i'll probably do is just send back success or something obviously in practice you would want to make this a lot longer and i don't know just send back something or check if the user has been deleted or something like that but this is just what i'm going to do for the purposes of this video so now that we've made this route let's try it out all we have to do is just submit a user by a request.body.id and i think i might even just destructure it so that it looks a little prettier and then i'll just pass it here i could i don't know make this a type of string or something but um there's really no point to because i think typescript doesn't really need to be used for something that's never going to be reassigned or read more than once so let's check out the request so it's a post request to delete user and let's pass an id to it and i'll pass this one and i have to make this json okay and we get back success now let me run the get all users request again and as you can see we are no longer getting the id that we just copied which was 5 f 8 9 which is no longer here so we have a route to delete user and we have a route to get user but how do i make these routes only allowed to be used by administrators because currently anyone in their grandmother can come into here and call these routes to get users and delete them so there's no protection on them whatsoever we can make a very simple middleware function that evaluates if a user is an administrator and if they are then we're able to pass it through and complete the call so let's build out that middleware to only allow certain people to call these routes and if they're not authenticated and they're not admins we're just going to give them an error so to create middleware is actually extremely simple all we have to do is define a function and then slap it in the middle before we call the request and the response and we actually have middleware sitting right here because it's in the middle of the call and the request and response callback so all we have to do is just slap middleware here i don't know just whatever you want and this would be a call to middleware or whatever function that we define so it's going to call this function every time that we try and access the route and you'll see what i mean in a minute so i'm going to define a middleware or a function to check if the user is an admin okay so i'm going to make my function called is administrator and i'll probably just put middleware on it so it makes more sense to you guys and it's not going to return anything so i'm going to leave this blank but because it's sitting in line with the request and response right here we have access to the request response in next that is attached to it now this is going to give us an error and it's going to say that they have implicit any types and to get rid of these we can just use express as interfaces that they defined and the next function interface okay and what we want to do is we actually want to grab the request object and try and get the user from it so we can do it a couple ways we can just say if request.user exists so we can just leave it blank because it's going to check if it's undefined or null or what we can do is we can destructure it which is probably the better way to go about it so i'm just going to do const request using const user okay okay now what we can do is we need to check if the user is logged in and we do this here by just grabbing the request user object so we can say is if request.user and it's going to perform a check if it's null or undefined but what we probably want to do is just destructure it like that oops um [Music] and let's see if there's a user we're gonna continue but if there's no user let's send back sorry you aren't logged in i guess um and okay so now that there's a user let's look in the database for the user so we're gonna do user which is our collections our connection to the database and we can do find one let's find one by user dot username matches username let's see okay so probably hmm find one user.username oh i wrote this backwards that's why so it's username and then user.username cool and it's going to tell me it doesn't exist so i'm probably just going to make it a type of any and that's my cheap little work around obviously we wanted to find the type interfaces and i'll probably do that at the end of this video but anyway so we're gonna look and find one then that takes a callback of either an error or the document and if there's an error so i'll just say if error sends i mean we i think i'm just going to throw the error okay and if there is a document which there is if there's no error so we'll just say if doc okay then we'll do then what we're going to do is we're going to check if they're admin so we're going to say if doc dot admin um and they're going to want me to define this and i'll do that with my interface that i did earlier which is user interface and it's is admin then i'm going to return back but obviously this is um it's possible that doc doesn't exist so yeah i'll probably just put this here just in case it doesn't exist so if it's admin then let's go ahead and send back or we'll call the next function which just means let's continue on with the route and if it's not an admin then we'll send back sorry not and admit only admins can perform this in a live application we probably don't want to send anything back we just want to leave this blank but okay so now we have a middleware that we can plug in to any of our routes and it's going to check if um you're logged in if you're logged in let's look you up are you an admin then if you're an admin then we can continue with the route so let's plug this guy in over to our routes that we defined such as here as well as right here okay so now we should not be able to perform this unless we are logged in and we are admins so let's try this out inside of postman first sorry you are not logged in and that's correct so what i'm going to do is move over to the admin page and sort of build out the request so that we can try and run it from a real admin so i'm probably going to use a use effect hook not probably that's definitely what i'm going to do it takes no dependency so i'm going to leave the array blank at the bottom and i'm going to just call axios.get and pass the url in okay and definitely pass the credentials because we need to see if they're an admin or not and if they're logged in and on the promise currently let's just log what the data says so what we're going to see on the admin page is i meant to inspect element okay so we're going to see a network error hmm so we can fix this error by just adding an else statement because uh we are unconditionally sending back that we're not logged in which was my bad okay and once the server starts we're gonna have to relog in and go to the admin page and we see sorry only admins can perform this that's also because it needs to have an all statement okay sorry about that and now we are going to be able to actually um use that middleware properly so what we're going to get back is an array of the people that are logged in now not that we can access this page but even if we could access this page from somebody who's not an admin we would certainly not be able to get these users back and i kind of just want to prove this by allowing this page to be accessed by anybody just so we can test this out so what i'm going to do is inside of the app i'm going to allow the route to the admin to unconditionally render just to show you that only our admin can access this route so let's go ahead and log out and let's login as a user one two three one two three so let me go to the admin page and we're gonna see sorry only admins can perform this so what we now have is a route that is protected with an administration middleware we created and we can only access if a user is an admin and we did this in an extremely small amount of code compared to other programming languages and other libraries so now that that's done let's move over to just displaying our data on the front end to look somewhat presentable and i'm probably going to do that by wrapping that or putting this response inside of state and then displaying it or something like that and i'm going to replace all of these um anys with interfaces at the end of the video so just stick around for that part but let's go ahead and just set the data to whatever the response is i'm also going to remove this change i did here so that we're back to how we used to render it so now what i'm going to do is i'm going to just map through the data set that we're given and allow an admin to delete the users from the website so we can simply do that by creating a select html tag and adding some options inside of it by mapping through the data i'll probably just give it a name of um delete user or something i don't know doesn't really matter and to add the option tags i'm just going to map through the data it's going to bug me here because i'm not defining what an item is so i'll come back to this later for now just define the item as any type so let's see let's just return a option tag and i think it wants an id so i'll just give it the username and it wants me to put the username inside as the name and i just put the username inside here as the name of it oops there we go cool so now what we need to do is we need to add an on change event handler to this select statement and the onchange event handler receives an event as a parameter just as an input element does and whatever this e is is going to be our value inside of our option so let's just store this up here in some state so that we can get the current user that's been selected and i think it's going to be stored as a string so i'll just make it a string okay and now i'm just gonna log out what it's storing it as okay so now if we check it out we can change this to nate back to one two three but you'll notice that it's undefined at first and we actually don't want that so what you'll see a lot of people do is create a option tag that's completely empty in the front and it'll probably just say like select a user or something and we'll give it an id of select a user so this is what you'll see a lot of people do so now we can actually store staple values like that so now that that's done let's actually create a button to delete the selected user and we can do that like this we'll attach an on click event to it and we'll say on click let's run a delete function and we'll call it um delete user and we'll define it up here and i think i called the route delete user yeah i did so we'll call that route and we'll pass the credentials to it because we still need to access this protected route oh but this is where we define the request.body in this first configuration object for post request so i'll put a comma and i'll put it in here okay so the second configuration object is going to be the options and the first one is going to be the data to send with it whenever you're using the post method from axios so the data i want to send to it is id and i will do wow i just realized so this username is what we're selecting but we're storing it as a username inside of the state but when we delete a user we need to submit an id so we could do this a couple ways we could map through our data set find the id and then send it um or we could just allow usernames or ids or just usernames it's entirely up to you but probably to stay consistent i'm gonna do the smart thing and just send the id to it because it's probably the right thing to do so let's map through a data set and i will see um if it matches so we'll grab selected user if the username matches selected.user then we will set the id to the item.id oops yeah so now we have to do is just put the id here um and send it with the request we defined the user id as being a string and we assigned it here to the item.id but we define the item as being any so we have no idea if we're assigning a string or not so what we can do to work around this is to just change this to any and it's going to fix the problem now later on we're going to define our item and we can erase this and add string instead so that's how to get rid of that error just change it to any for now and one last thing before we send this off is we have to change this to underscore id because that's what the fields are inside of the database so we're saying let's map through the data if the item.username which is the item we're mapping on is equal to the user we've selected then let's set the id up here to be the item we're mapping on underscore id so now if we just delete the user we won't see the user anymore and ignore this console log that you just saw over here i just ran a console.log because i was a little confused about something but yeah make sure you add this underscore id and everything will work fine so now we can delete users only admins can delete users and we're seeing our own our own account here that we're able to delete and that's obviously not ideal so what we can do is we can go back to the admin page and let's make sure that when we call this use effect hook we set the data to everything except for our current um our current user because we don't want an admin to be able to delete themselves so we can do that like this let's grab the context to see who's currently logged in i'm going to copy the code from over in the app like this copy and move back over and let's paste our context so that we have it i'll do imports and let me just log out the context real quick so we can see the current logged in user okay so the username is nate i'm going to say let's set the data to everything except for the context.username so we can do that by adding a filter method so i'll do it like this okay so i'm calling a filter method and i am saying for every item that we iterate through only return if the item.username does not equal context.username so now if we log the data we will see that we are getting every user except the current user oh it's saying expected an assignment call and set saw in expression so let's just add a return statement okay and what we're going to see is an array that's empty because the only user is us so we're not going to see ourselves cool so if we create a bunch of users we will not see them here so let's go ahead and try this out i'm going to register a ton of users okay and we'll make another user a few more and probably the last one so now if i log in as any of these users and i just want to show you the problem we have here so this error is pretty much telling us that there's a 401 error coming back and et cetera et cetera what's really going on is we didn't add any handling for if the user doesn't exist and we're trying to log them in but i'm going to handle this in just a minute first off let me log in as an admin and we'll come back to this in just a minute okay let me just go over to here and we see all of the users that we have i'm gonna delete asd and refresh and they're no longer there cool so we can delete a ton of users if we'd like to okay so to handle that error we just saw where we are not able to log in if the user doesn't exist we can handle that error and send something meaningful back like so all we have to do is head over to our login where we're actually submitting our login request and as you can see right here we have a promise but this is a promise for if it completes successfully what we need to do is add a comma and you'll see here on rejected meaning that we've failed you can handle this in a million ways but i just want to log failure i'm not going to give a reason um it's kind of smart not to give a reason in most modern applications but let's just do that okay so now we're going to see failure which is perfect now if you actually go to the network tab and you see this 401 we get an error when we post it and it just says unauthorized now this is all handled by password by the way so they handle this over here in the index which i accidentally just closed just now but up here what you see is we are saying if there's no error return null false which means return unauthorized back to the client so whenever you see no false it means return unauthorized now if it's true return no user which doesn't mean unauthorized it then passes it to the serialize user function so what we can do now is so taking a look at where we're at inside of our react application is we have a navbar which is leading us everywhere that we need to go in our application and we even can log out of our application and we are conditionally rendering all of our links that we have we have all of our pages we have an ad administration page where we can delete users if we're admins we have a context page that's passing all of the stateful value of who's logged in to each component that we wrapped it in we have the home page here which is just the default home page to show you that we can have multiple pages in a react application we have a login page so that we can log users in at any time and we even have a failure option for when the request fails now we have a profile which is also just to show you i guess because i'm passing this in the video i will just throw in here the currently logged in user i'm going to grab the context i'll just paste it because i'm too lazy to write it out and i'll just throw in here context.username cool so at this point we have a full application protected apis and the protected rendering inside of react or the conditional rendering inside of react so what i want to do now is dedicate this video to cleaning this file um cleaning up all of our files and making everything actually typescript worthy by putting interfaces into things and defining what we want our types to be so i'm going to do that now so this error here is telling us that we're missing a dependency inside of our dependency array or use effect hook and what that means is that the context which we're using is a dependency and the use effect depends on this context so we need to put that in the in this array here to tell it hey every time this dependency changes rerun the hook so that's why i like react for debugging um is that that's a cool little error catches there so now that that's finished i noticed another problem and that's that the data we're sending back is inconsistent for example this request.user object is being created from the deserialize user function so this to serialize user is sending back the username and the is admin and it's storing it on the request.user property so what i'm trying to say in this is that we're missing the id inside of our user information or inside of our context so i'll show you an example of this real quick but i really dislike having inconsistent data being sent back and i can fix that pretty easily so on the admin page i'm just going to log what our context is so let me log in here and go to the admin where i i'm logging it and you see we have username and the is admin so that context is coming from the request.user object and that's coming from the deserialize user function so when i change this user information which is being used in the callback it's going to change the data that gets sent back i want to pass the id to it so i have the id of every user in my context so let me do that so now i'm able to get back my user from the database or the id from the database so that's going to keep our data a little more consistent because we have the username is admin and id all attached another thing that's extremely inconsistent and a really bad idea is that over in the get all users route we're sending back all of the data from our database including the user's hashed passwords and the data is extremely inconsistent from what we have going on so to make this more consistent i'm going to map through our data and i want to make it return a bunch of users that all have this exact oops this exact same style to the data the username is admin and the id so currently what it's sending back is look i'll just log it out here so you can see so let me log out what the data is coming back as currently so here let me log in again go to the page and we're getting this here underscore id underscore v is admin password and username and what we should be getting back is an array that looks like this so that our data is consistent so that we can build a stronger application so i'm going to do that by filtering the data that i'm sending back here by probably throwing it in a for each and using some trickery so don't get lost here just try and follow along and look at the code for a little while if this confuses you and i'm going to make this a type of any because it's going to be changing and you'll see why in a minute i'm also going to make this a type of any as well and now i'm going to change the object that i want to send back so i want an id i want the username and i want the is admin and what i need to grab it from is the item dot underscore id from the item.username and the item dot is admin and let's see what the error says oh just missing some commas okay so now i have the revised user information and i'm going to push it to the new array of users that i want to return so now this new array of users contains my filtered data that i've created and i'm going to send back this new array instead of the old one that i was previously sending back so now our data is going to be consistent and when we get all the users from the database we get them back correctly with the data in a consistent manner so as you can see we now have the id username and the is admin we're not sending back any hash passwords and all of our data looks consistent so now that we're getting back the data correctly let's go back to the frontend and let's build some interfaces so that we can make our application have auto completion and all of the awesome typescript benefits by interfacing our objects so in the src i'm going to create a new folder and just title it interfaces i'm going to make a file and also call it interfaces and this user interface is going to be pretty much a model of the data that we're getting back so if this is the data we're getting back we know the id is a string the username is a string and the is admin is a boolean so now we can use this interface every single time we are defining a user which we do a unbelievable amount throughout our application so hang tight and i'm just going to replace all of our annie's and try and throw this as many places as i possibly can i'm going to make the response or get all users to be an interface of type axios response and right here where i'm filtering through the data we're going to be having a type of user interface which we've just defined because the data we're getting back as a user is an array of users when we filter through them each item will be a user interface so now if you actually look at what changing the type does when we hold control space we have all of the properties that our user interface defines it as and if we put something random in there it'll tell us hey that doesn't exist on our user interface so that's kind of the awesome thing about typescript so let's also do the same thing over here we want to define our data in our admin page to be an array of user interfaces i'm going to make my user id that i'm deleting a string and over here where we're receiving this error it's because it doesn't know that our user id which we've defined here has been assigned because if we're mapping through all of our data with our for each loop what if the item.username does not equal the selected user because us as humans know that that's absolutely impossible that if the selected user is even appearing in our options then obviously he exists in our data set then there's no way this would ever be false and this one it run true us as humans know that this is always going to be true so we can just put an exclamation mark saying hey we know for a fact there's going to be a definition for user id so the explanation operator just pretty much says leave me alone i'm a human and i know better than you so let's add that there when we're mapping through our data down here each item that we map through is also going to be a type of user interface so now we have a full page that is completed with as many typescript things as i can come up with on the spot we can also define our events here as being types of event object but this is probably not necessary but if you really want to go the extra mile you can define everything to be typescript but not really going to do that for this video so over in our user we also want to define this in our context i'm just going down each page and defining as many things as i can so let's change the state or the type of this i'm going to also change this to an axios response type and now i'm also going to change the type of the context because i know that my context is going to be a type of user interface so i can change that here but now what we run into is it tells us hey we can assign this object this empty object to it if we remove it we'll get an error saying that we need to assign something as a default value so we can do is we can just wrap it inside of a partial which is a very strange looking thing to do but all this does is it pretty much just says we're initializing it with the default value so that'll leave us a loan there so now we get an error down here that says type user interface or undefined is not assignable to type partial or user interface so what this is pretty much trying to tell us is that we don't know if there's going to be any value inside of here our value currently is defined as the user which is a type of user interface and we're setting it here from our use effect hook so that it leaves us alone we'll slap an exclamation operator on it saying leave us alone we're humans and we're smarter than you and that way the context now has types and it works perfectly so if you actually hover over the context you'll see we have our type so we don't need to define our context variable okay so let's move on to defining the next thing down the list which is a home page doesn't need any definition let's define the login with their types so let's see i know my response is an axios response and res.data is success log failure all this looks okay so how about profile that's fine register that's also fine okay and navbar and now check this out notice how that we've added over on the context we've added the types for it take a look at how it has the auto completion here so that we can add anything we want that means that it's interfaced properly and that we can expect what data is going to be there so the next thing i want to do is head over and clean up our back end so i want to add proper interfaces and i want to utilize the dot env package so that we can hide our connection string inside of environment variables so i can do that by creating a new file and i'm going to title it dot env and make sure to do it in the main folder of your application i'm going to start off by just pasting the connection string accidentally pasted a quote there okay so we're supposed to honestly give it a database name i'm probably going to give a db name of users but uh it doesn't really matter i'll just leave that blank so take a look here so we want to separate the string into different parts we want to store the beginning part of the string like so i'll store the username like this i'll probably take this thing off store the password and store the second part of the string so let's start titling this part one string username password and i'll do part two so now we can grab all these properties when we go over to our page by using the dot env package so i can erase this connection string and instead i'll put template literals like so and i'll start off with the first part of the string which is defined here so i think it would be smart if i just kept a copy of the string just so you can examine the differences between the template literal and the real string so i'm going to start off by putting part 1 string so we can do process dot env dot part 1 string because the dot env package stores all of our environment variables inside of the process.env dot and then the name of it so i have part one string and then we have the username right after so i'll do the process.enb and then.username and notice how i have this colon in the middle before i add the password i'll make sure to put that there then i'll put the password and then i'll put the last part of the string and if we log this connection string out it will be the equivalent of this over here now the last thing that we need to do is we need to call the config from dot env like this now what this config does is that when the application starts it grabs everything from your environment and stores it as variables you can use so that is what the config method does and that's why we need to call it at the beginning of every application so now if we start the server we will have the connection string the exact same as it was before but our environment variables store the sensitive data so now no one can read the string when we use this in production the next thing we need to do is i want to interface for the for what the database uses to store a user so i'll do like this and i also notice up here that we are putting the password in the user interface which is not the way it's supposed to be so i'll do id string and i forgot that inside of interfaces we use semicolons and not commas and i also need to add semicolons here okay it won't give you an error it's just a neater thing to do sorry so now that we have a interface for how the database stores a user and we have an interface for how we personally store a user we can plug these in everywhere so that we can have a bunch of type checking done for us so let's make sure to just add a bunch of types to everything out okay and serialize user is going to return a database user interface and that is going to make this underscore id so in our serialized user we were serializing it by i dot id it should actually be dot underscore id but you won't get an error for this um so don't worry you can do either one you want but to be consistent with the types that i've just defined i'm going to make this underscore id or it'll give me an error so but either one works you can do no underscore or underscore i'm just doing that so that typescript leaves it alone so now when we deserialize we can change all of these interfaces as well because we're finding one from the database the user we get back will be the database user interface which is this guy so this is what is going to send back when we expect a user so i'm also going to make this user information a type of user interface so now in the register we can change these around as well we want to change this as well to database user interface because whenever we're calling mongodb and we're connecting to our database and grabbing user from there it's always going to look like this and not this we're going to see a password we're going to see our underscore id so make sure that the document always comes back with the interface of database user interface okay and moving on this needs to be a database user interface as well because we're not using the request object here we can leave it as an underscore but it honestly doesn't matter um i mean if you [Music] if you have like an es lint or something or some type of linter setup it's going to give you an error but and anyways moving on here and over down here we're going to change some of this now the very last final touches that i want to add is just a little bit of cleanup so that we can take care of some error handling and the final touches so i really don't see the point in this interface here i don't like to define interfaces for example like this error here when we're never using it more than once and we're not using anything meaningful with it so if i was using in an application and i wanted to see which property the error was or i was doing something new with it i might define it then but for the purposes of this application defining the interface for our error is not really something that we need to do so i'm going to just delete all of my definitions for error okay that's one and then the final one is the definition okay another thing as well is the request and response that we defined here is also completely unnecessary because like i said we're not doing anything too meaningful with it that is necessary okay and we have to define the request response and next function here because if we don't we will get an error because over here we're using the app express so it defines this enough to leave us alone over here we're making a custom function so we have no choice we have to use these interfaces or else we'll get an error also what i want to do is every time that i'm grabbing the request.body i want to make sure that i put a question mark because i don't want to get an error if there is no request out body so that way we don't have a destructuring error so if we can't destructure it'll just return undefined another thing is that the is admin right here which we are defining when we create a user in the register route is there is admin is still set to true we only set this earlier so that we could make one admin true and i forgot to turn this back off so let's make sure that we make this false or just delete the key in general so that that way it uses its default value which is false so now that's fixed and every regist every person that registers will not be an admin the last thing is i will do a format okay so just a simple format and we should be good to go now and now we've completed our entire server and wrote the entire thing in typescript with everything interfaced properly and their types defined i missed some semicolons along the way but everything um is pretty much the way it needs to be so this is how you build a typescript react and node.js server with protected routes and protected endpoints in an api if you made it this far please drop a like it would seriously help and drop a comment telling me the next video i should make and your opinions on this current one thanks so much for watching guys i'll see you in the next video
Info
Channel: Nathaniel Woodbury
Views: 9,479
Rating: undefined out of 5
Keywords:
Id: Gwru3BueuiE
Channel Id: undefined
Length: 138min 2sec (8282 seconds)
Published: Mon Oct 19 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.