3.1 User Accounts Overview
If you’re more interested in the front-end code, you don’t have to watch the other lessons in this chapter. This lesson will give you a brief overview of the user accounts functionality. If you want to learn how it all works in greater detail, continue with the rest of the chapter. Otherwise, you can retrieve this code form the course GitHub repository and skip to chapter 4.
1.Getting Started2 lessons, 03:51
2.Project Setup3 lessons, 20:58
3.Server-Side Code6 lessons, 53:00
4.The Client Side16 lessons, 2:43:53
5.Conclusion1 lesson, 00:29
3.1 User Accounts Overview
In this lesson, we're going to do a quick overview of our user account system. Now this lesson is for the people who don't want to look at too much server side code, they just wanna focus on the react and flux stuff that we're going to be doing on the front end. If that's you, then feel free to just watch this video and skip the next couple of lessons about building our user account system on the server side. If you aren't interested in following through the building of the user account system, then you can probably skip the rest of this lesson, and move on to the next one. So what we're looking at right here is the login template. And this template will have two forms. As you can see, right here we have a login form which we'll be posting to the /login route. And this will take a username and a password. Underneath this we have another form which we'll post to the signup route. And this will take the full name, email, username, and password of our user. And this is what the user will use if they are creating a new account or coming to our app for the first time. Now the server is set up and running, so you can see this in action if I go to localhost:3000/login. And you can see in the left here, we have our Log In form and on the right, we have our Sign Up form. Now this looks nice, but we need the routes that will be behind that, right? So let's look back at this login.js file. We're using passport, which is a node package that allows you to create user accounts. So we have passport and then passport local, which is the local strategy, which means we are creating accounts that we manage on our own database. Speaking of databases, we're using locallyDB, which is a little NPM package which allows you treat a JSON file as if it is a MongoDB style database. So we're creating a database right here and we're using a users collection. So we have our passport strategy right here. This is where we check the database for a username and a passwordHash that currently exists. And this code is run when the user tries to log in. So if that username and passwordHash do exist, then right here we pass that user object to the done method. And so the user is logged in. If it doesn't exist, then we pass false and the user will be redirected back to that /login page. We need a way to serialize and deserialize the users, so they can be used in one session over multiple requests. So that's what this code does. It's very simple, it just takes the user ID to serialize it and then uses that ID to get the user out of the collection to deserialize it. Then we have a bunch of routes here. So we create an express router object, and then we pass it body parsing for both URL encoded bodies which is the forms in our log in page. And then we also want to parse JSON bodies and we are using this for our API that will be in a separate file. We include cookie parsing and express-session, so that we can manage the user's session, which is multiple requests of course. Then we let express know about passport by passing the express router our two pieces of express middleware, passport.initialize, and passport.session. So then we come to the routes that our login system uses. When the user gets the /login route, we'll just render that template that we looked at. Then, when they post to the signup route, this happens when they click the sign up button in the sign up form, we start by checking to see if a user with that username already exists, and if it does we just redirect back to login. Otherwise we'll create our user object here, store it in the database, and then log that user in. Now if the user already has an account, then they'll probably click the login button, in which case we will post to the login route here. For this we don't have to write our own middleware, because passport has it for us, we use passport.authenticate with our local strategy. And if we're successfully logged in, we will redirect to the home route, otherwise we will redirect to the /login route. And then of course we just create a logout route which will just log the user out and then redirect them to the login route. Now for some of our routes, like our home page, which is where our application is, or for several of the different routes in our API. We'll wanna make sure the user is logged in before they can view the resource at the end of that route. And so this function here is what we'll use to make sure they're logged in. Since it will be used as middleware, we take the request, response and next functions as the parameters and then the request object has an isAuthenticated function that passport gives it. If that returns true, we just move on to the next piece of middleware otherwise, we'll redirect to the /login route. Finally, we have a function that will make the user safe. Because we have these user objects that we're gonna want to send to our client side, we want to make sure we don't send any data that would be better kept private, for example, our passwordHash field. So we create a safeUser object. We have a list of safe keys. And then we just loop over that list of safe keys and copy them all off the user object that was passed to make user safe. And then we return our safeUser. Finally, we put our router object, our loginRequired function and our makeUserSafe function all on our exports object here. So that we can access them from other places where we require this module. That other place, of course, is server.js. As you could see at the top here, we're requiring our login file. And then you can see here in our list of middleware, underneath express.static, we're using our login.routes. And this is how we can use an express router object. We just pass it to our use method on our express application object and this routes will be used. Then we're actually also using login.required, as you can see, we pass that as a first function here to our catchall get route. This shows one of the cool features of express. We can actually pass multiple functions to a route creator, and they will each be run sequentially. So login.required here will be run first, and if it calls .next, then this function will be called. So, if the user is logged in, this function will be called. Otherwise, it will redirect to /login. So, this way we can make sure that only logged in users see our index template. Finally, we are passing some data to this index template. As you can see, we have a second parameter here, which is an object. We have a user property and we use our login.safe function to make a safe version of the currently logged in user. So then, in index.ejs we can add another script tag here, which is our global object for our logged in user. And then we just use JSON.stringify over that user so we can get that user as JSON on the client side. So now we can see all of this working together in action if we go here to our login route. I have already created a user, so let me go ahead and log in. And notice if I put in a wrong password and try to log in we're redirected back to /login here. However, if I put in the right username and the right password then I'm successfully logged in. Now there's currently nothing to view on this page. However, if we go to our elements tab in our developer tools and look at the first script tag, you can see that our user object here was successfully sent from the server to the client. Which means that this user was successfully logged in. As a final example here I can go to /logout, and you can see that I'm logged out because we're redirected back to login. And now if I try to go to the home route I'm redirected back to login. All right, so that was a quick look at how the user account system in this application worked. And so, if you're not interested in seeing all the details of that, you can skip the next couple of lessons, and pick up where we start creating the Chirps API.