title
Adding User Signup | Creating a REST API with Node.js

description
Time to add authentication to the RESTful API. Let's start with user signup. ---------- Learn Node.js in our comprehensive 30h+ course: https://acad.link/nodejs Source Code: https://github.com/academind/node-restful-api-tutorial/tree/10-auth-signup More about JWT: https://jwt.io/ bcrypt Github Repo: https://github.com/kelektiv/node.bcrypt.js ---------- • You can follow Max on Twitter (@maxedapps). • You can also find us on Facebook.(https://www.facebook.com/academindchannel/) • Or visit our Website (https://www.academind.com) and subscribe to our newsletter! See you in the videos!

detail
{'title': 'Adding User Signup | Creating a REST API with Node.js', 'heatmap': [{'end': 959.424, 'start': 934.174, 'weight': 0.758}, {'end': 1098.565, 'start': 1021.466, 'weight': 1}, {'end': 1145.066, 'start': 1122.851, 'weight': 0.9}, {'end': 1325.62, 'start': 1299.77, 'weight': 0.798}, {'end': 1652.393, 'start': 1630.465, 'weight': 0.716}], 'summary': 'Tutorial series covers implementing authentication in a restful service with node.js, including client-server authentication, creating user model and routes, user creation, validation, handling user existence, and cleanup process, emphasizing resource access control, jwt usage, and security measures like password hashing and email validation.', 'chapters': [{'end': 73.304, 'segs': [{'end': 73.304, 'src': 'embed', 'start': 2.91, 'weight': 0, 'content': [{'end': 3.791, 'text': 'Welcome to this video.', 'start': 2.91, 'duration': 0.881}, {'end': 8.037, 'text': "Let's continue building our RESTful service with Node.js.", 'start': 4.172, 'duration': 3.865}, {'end': 20.073, 'text': 'And in this video I want to start adding authentication so that we can ensure that certain resources on our server are only available to users who are logged in.', 'start': 8.678, 'duration': 11.395}, {'end': 26.939, 'text': 'Now, of course, one important question will be how we actually implement authentication in a RESTful service,', 'start': 20.734, 'duration': 6.205}, {'end': 31.522, 'text': "because it's different to your normal Node.js application you might have written.", 'start': 26.939, 'duration': 4.583}, {'end': 36.826, 'text': "And I'll have a look at this and then, of course, actually implement it in our project in this video.", 'start': 32.023, 'duration': 4.803}, {'end': 37.487, 'text': "So let's start.", 'start': 36.946, 'duration': 0.541}, {'end': 47.929, 'text': "Let's start by first understanding how authentication works in a RESTful service as we are building it.", 'start': 42.006, 'duration': 5.923}, {'end': 50.43, 'text': 'So we get a client and a server.', 'start': 48.61, 'duration': 1.82}, {'end': 55.833, 'text': "And remember, a client is, for example, your web app you're building.", 'start': 50.831, 'duration': 5.002}, {'end': 64.598, 'text': 'So the front end facing, the client facing web app, which you might write with a framework like Angular, React or Vue or with a vanilla JavaScript.', 'start': 56.013, 'duration': 8.585}, {'end': 72.063, 'text': 'Or any other client could be a mobile app that connects to a back end to also have a data layer to be able to store data and fetch data.', 'start': 65.078, 'duration': 6.985}, {'end': 73.304, 'text': 'These are your clients.', 'start': 72.303, 'duration': 1.001}], 'summary': 'Building restful service with node.js, adding authentication for logged-in users.', 'duration': 70.394, 'max_score': 2.91, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE2910.jpg'}], 'start': 2.91, 'title': 'Implementing authentication in restful service', 'summary': 'Discusses implementing authentication in a restful service with node.js, emphasizing resource access control for logged-in users and its relevance to client-server interaction.', 'chapters': [{'end': 73.304, 'start': 2.91, 'title': 'Implementing authentication in restful service', 'summary': 'Focuses on implementing authentication in a restful service with node.js and discusses the importance of ensuring certain resources are only accessible to logged-in users, explaining the process of authentication and its relevance to client-server interaction.', 'duration': 70.394, 'highlights': ['Authentication is crucial for ensuring that certain resources on the server are only available to logged-in users. None', 'The chapter covers the process of implementing authentication in a RESTful service with Node.js. None', 'Explains the significance of understanding how authentication works in a RESTful service, particularly in the context of client-server interaction. None', 'Discusses the clients that interact with the server, including web apps and mobile apps, and emphasizes the importance of implementing authentication for these clients. None']}], 'duration': 70.394, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE2910.jpg', 'highlights': ['The chapter covers the process of implementing authentication in a RESTful service with Node.js.', 'Discussing the clients that interact with the server, including web apps and mobile apps.', 'Authentication is crucial for ensuring that certain resources on the server are only available to logged-in users.', 'Explains the significance of understanding how authentication works in a RESTful service.']}, {'end': 377.905, 'segs': [{'end': 117.864, 'src': 'embed', 'start': 73.684, 'weight': 1, 'content': [{'end': 78.247, 'text': 'I talked about them earlier in this series, so make sure to go through all the earlier videos too.', 'start': 73.684, 'duration': 4.563}, {'end': 80.368, 'text': "So that's our client, that's our server.", 'start': 78.847, 'duration': 1.521}, {'end': 85.532, 'text': 'Now we want to log in and for that the client is going to send some off data to the server.', 'start': 80.929, 'duration': 4.603}, {'end': 92.637, 'text': 'With off data I mean email address and password of a user if we have a typical email and password authentication flow.', 'start': 85.652, 'duration': 6.985}, {'end': 101.039, 'text': "On the server, we then, if we're signing up, we can then store this data in the database by hashing the password and storing it and so on.", 'start': 93.577, 'duration': 7.462}, {'end': 109.322, 'text': 'Or if the user is logging in because he already did sign up in the past, then we would simply check these values on the server.', 'start': 101.92, 'duration': 7.402}, {'end': 117.864, 'text': "So we would verify if the user who's sending us this data actually has a valid account for this given data on our page.", 'start': 109.642, 'duration': 8.222}], 'summary': 'Client sends off data to server for login or signup.', 'duration': 44.18, 'max_score': 73.684, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE73684.jpg'}, {'end': 287.796, 'src': 'embed', 'start': 241.661, 'weight': 0, 'content': [{'end': 246.403, 'text': "but in a way that we can always check if it's valid on the server.", 'start': 241.661, 'duration': 4.742}, {'end': 253.645, 'text': "That's of course important, otherwise anyone could send us a token and if we just check if a token is there, then this would not be very secure.", 'start': 246.763, 'duration': 6.882}, {'end': 258.286, 'text': 'But by being able to verify this token, well, it is actually pretty secure.', 'start': 253.945, 'duration': 4.341}, {'end': 260.487, 'text': "Let's have a closer look at this token though.", 'start': 258.846, 'duration': 1.641}, {'end': 264.368, 'text': 'So this token is called a JSON web token.', 'start': 261.067, 'duration': 3.301}, {'end': 272.211, 'text': 'typically, or typically, we use this format to be precise because it simply is just a JSON data object in the end,', 'start': 264.368, 'duration': 7.843}, {'end': 279.853, 'text': 'where we can add some information like the ID of the user or the email address of the user who is signed in, and some signature.', 'start': 272.211, 'duration': 7.642}, {'end': 281.954, 'text': 'So these two pieces are important.', 'start': 280.053, 'duration': 1.901}, {'end': 287.796, 'text': 'It also contains data about when the token is going to be expired and the issuer of the token.', 'start': 282.554, 'duration': 5.242}], 'summary': 'Json web token ensures secure user authentication and contains user info and expiration details.', 'duration': 46.135, 'max_score': 241.661, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE241661.jpg'}, {'end': 340.107, 'src': 'embed', 'start': 311.556, 'weight': 4, 'content': [{'end': 319.858, 'text': 'we could find out that it is not a valid token on the server because we use a private public key combination and only the server knows the private key.', 'start': 311.556, 'duration': 8.302}, {'end': 325.24, 'text': 'So only the server has both keys it needs to in the end validate this token.', 'start': 320.099, 'duration': 5.141}, {'end': 328.401, 'text': 'One important note though, the token is not encrypted.', 'start': 325.94, 'duration': 2.461}, {'end': 332.923, 'text': 'So once we got it on the client, we can actually have a look at it.', 'start': 328.721, 'duration': 4.202}, {'end': 340.107, 'text': "we can extract the data from it, but as i said, if we try to change it well, that doesn't do anything.", 'start': 332.923, 'duration': 7.184}], 'summary': 'Server uses private-public key combo to validate tokens; tokens not encrypted.', 'duration': 28.551, 'max_score': 311.556, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE311556.jpg'}], 'start': 73.684, 'title': 'Client-server authentication and jwt', 'summary': 'Covers client-server authentication flow, including the process of sending user authentication data and the use of json web tokens for authentication, ensuring secure access to resources by providing a token with user information and signatures.', 'chapters': [{'end': 117.864, 'start': 73.684, 'title': 'Client-server authentication flow', 'summary': "Covers the client-server authentication flow, including the process of sending user authentication data from the client to the server and the server's actions for signing up and logging in, with a focus on hashing passwords and verifying user data.", 'duration': 44.18, 'highlights': ['Client sends user authentication data (email and password) to the server for logging in or signing up, with the server storing the data in the database by hashing the password and verifying user data.', 'The server verifies if the user sending the data has a valid account on the page, ensuring secure authentication.']}, {'end': 377.905, 'start': 118.184, 'title': 'Using json web tokens for authentication', 'summary': 'Outlines the use of json web tokens for authentication in a stateless, restful service, ensuring secure access to resources by providing a token with user information and signatures, which can be verified on the server using a private public key combination.', 'duration': 259.721, 'highlights': ['JSON web tokens are used for authentication in a stateless, restful service, providing a token with user information and signatures, which can be verified on the server using a private public key combination. This method ensures secure access to resources and avoids the use of sessions, catering to various client types and allowing verification of token validity on the server.', 'The token contains user information, such as the user ID and email address, along with a signature and expiry data, making up a JSON web token. This ensures that the token can be verified on the server, preventing unauthorized access and maintaining data integrity.', "The token is not encrypted, allowing its data to be extracted on the client, but it can still be verified on the server using the private public key combination. This approach provides transparency for the client while ensuring the security of the token's integrity and preventing tampering."]}], 'duration': 304.221, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE73684.jpg', 'highlights': ['JSON web tokens provide secure access to resources and avoid the use of sessions.', 'Client sends user authentication data to the server for logging in or signing up.', 'Server verifies if the user sending the data has a valid account on the page.', 'Token contains user information, user ID, email address, signature, and expiry data.', 'Token can be verified on the server using a private public key combination.']}, {'end': 893.852, 'segs': [{'end': 455.849, 'src': 'embed', 'start': 425.709, 'weight': 3, 'content': [{'end': 431.353, 'text': 'So these two fields need to be given or need to be there if we create a new user model.', 'start': 425.709, 'duration': 5.644}, {'end': 441.34, 'text': "now. we can revisit this later to also add connections to products or orders, but for now let's keep it simple and let's focus on the authentication part.", 'start': 432.293, 'duration': 9.047}, {'end': 443.842, 'text': 'so this is how a user should look like now.', 'start': 441.34, 'duration': 2.502}, {'end': 445.404, 'text': 'i also need routes for the user,', 'start': 443.842, 'duration': 1.562}, {'end': 455.849, 'text': "so i'll add my user.js file here in the routes folder and And I'm going to set up the routes file in the same way I did for the other routes.", 'start': 445.404, 'duration': 10.445}], 'summary': 'Create user model with authentication and routes.', 'duration': 30.14, 'max_score': 425.709, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE425709.jpg'}, {'end': 532.503, 'src': 'embed', 'start': 507.148, 'weight': 2, 'content': [{'end': 515.033, 'text': "Overall, the path will be user slash sign up, but I'll load these routes just as I load the other routes from within app.js,", 'start': 507.148, 'duration': 7.885}, {'end': 521.216, 'text': 'by importing it here and then using a certain prefix and then pointing to the routes file.', 'start': 515.033, 'duration': 6.183}, {'end': 522.636, 'text': 'But that will be the next step.', 'start': 521.476, 'duration': 1.16}, {'end': 525.719, 'text': "Now, for now, let's simply create our sign up route here.", 'start': 522.837, 'duration': 2.882}, {'end': 528.721, 'text': 'Of course, we create the routes just as we did in the other files.', 'start': 526.159, 'duration': 2.562}, {'end': 532.503, 'text': "So I'll add a second argument where we get the request,", 'start': 529.161, 'duration': 3.342}], 'summary': 'Creating a user sign up route with imported routes in app.js.', 'duration': 25.355, 'max_score': 507.148, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE507148.jpg'}, {'end': 688.733, 'src': 'embed', 'start': 665.42, 'weight': 1, 'content': [{'end': 673.764, 'text': 'be that an employee or an attacker of our website, then all our user passwords are going to be readable, just like that.', 'start': 665.42, 'duration': 8.344}, {'end': 675.424, 'text': "we don't want that.", 'start': 673.764, 'duration': 1.66}, {'end': 681.247, 'text': "so we need to encrypt our password, we need to hash it, and for that we'll use a package.", 'start': 675.424, 'duration': 5.823}, {'end': 685.052, 'text': "we'll use node-bcrypt.js.", 'start': 682.711, 'duration': 2.341}, {'end': 688.733, 'text': 'Now, GitHub link can be found in the video description.', 'start': 685.832, 'duration': 2.901}], 'summary': 'Encrypt user passwords with node-bcrypt.js to prevent unauthorized access.', 'duration': 23.313, 'max_score': 665.42, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE665420.jpg'}, {'end': 879.906, 'src': 'embed', 'start': 851.079, 'weight': 0, 'content': [{'end': 859.081, 'text': 'the idea behind salting is that we add random strings to that plain text password before we hash it,', 'start': 851.079, 'duration': 8.002}, {'end': 864.042, 'text': 'and then the strings that were added are also stored in the hash.', 'start': 859.981, 'duration': 4.061}, {'end': 871.284, 'text': "By doing it like this googling the hash won't lead to the plain text version of the password,", 'start': 864.782, 'duration': 6.502}, {'end': 879.906, 'text': "simply because the plain text version contains a random string and we don't have hashing tables, dictionary tables for all kinds of random strings.", 'start': 871.284, 'duration': 8.622}], 'summary': 'Salting involves adding random strings to plain text passwords before hashing, preventing hash cracking by adding complexity.', 'duration': 28.827, 'max_score': 851.079, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE851079.jpg'}], 'start': 377.905, 'title': 'Creating user model and routes', 'summary': 'Involves creating a new user model with fields for id, email, and password, and setting up user routes for sign up and sign in. it also discusses the importance of hashing passwords for security using bcrypt.', 'chapters': [{'end': 425.688, 'start': 377.905, 'title': 'Creating user model for app', 'summary': 'Involves creating a new user model named user.js, with fields for id, email, and password, defined as required strings.', 'duration': 47.783, 'highlights': ['Creating a new user model named user.js with fields for ID, email, and password', 'Defining email and password as required strings']}, {'end': 893.852, 'start': 425.709, 'title': 'Setting up user routes and hashing passwords', 'summary': 'Focuses on setting up user routes for sign up and sign in, and discusses the importance of hashing passwords to ensure security, highlighting the use of bcrypt to achieve this.', 'duration': 468.143, 'highlights': ['Setting up User Routes The chapter emphasizes the creation of user routes for sign up and sign in, and the decision not to include a log out route due to the absence of stored user information on the server.', 'Creating a New User It details the process of creating a new user, including importing the user model, defining user fields, and handling email and password inputs from the request.', 'Importance of Password Hashing The significance of password hashing is highlighted, discussing the security flaw of storing plain text passwords in the database and the vulnerability it poses if the database is compromised.', 'Using bcrypt for Password Hashing The use of bcrypt for hashing passwords is explained, emphasizing the secure hashing process and the concept of salting to prevent lookup in dictionary tables, with the recommended 10 salting rounds for enhanced security.']}], 'duration': 515.947, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE377905.jpg', 'highlights': ['Importance of Password Hashing: Discusses security flaw of storing plain text passwords', 'Using bcrypt for Password Hashing: Emphasizes secure hashing process and salting concept', 'Setting up User Routes: Emphasizes creation of user routes for sign up and sign in', 'Creating a New User: Details process of importing user model and handling user fields']}, {'end': 1276.334, 'segs': [{'end': 920.887, 'src': 'embed', 'start': 894.293, 'weight': 1, 'content': [{'end': 901.196, 'text': 'This is a function where we, as you can see in the documentation, either get an error or we get the hashed password.', 'start': 894.293, 'duration': 6.903}, {'end': 903.177, 'text': 'So we have these two arguments.', 'start': 901.376, 'duration': 1.801}, {'end': 906.098, 'text': 'And then we can check if we got an error here.', 'start': 903.857, 'duration': 2.241}, {'end': 917.725, 'text': 'Then we want to return a response where we send status code 500 and a JSON object where we maybe set an error object which contains our error.', 'start': 906.659, 'duration': 11.066}, {'end': 920.887, 'text': 'So then we simply know, okay, this failed.', 'start': 918.065, 'duration': 2.822}], 'summary': 'Function checks for error and returns status code 500 and error object if failed.', 'duration': 26.594, 'max_score': 894.293, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE894293.jpg'}, {'end': 979.078, 'src': 'heatmap', 'start': 934.174, 'weight': 0, 'content': [{'end': 937.135, 'text': 'So what we need to do actually is change our code.', 'start': 934.174, 'duration': 2.961}, {'end': 941.738, 'text': "We don't assign this to password because it's no synchronous operation.", 'start': 937.616, 'duration': 4.122}, {'end': 950.861, 'text': 'instead here this bcrypt operation is what we execute first and only if we make it into the else case.', 'start': 942.558, 'duration': 8.303}, {'end': 959.424, 'text': "only in this case we'll create a new user, but then in the else case we got a password value and that will be the hash.", 'start': 950.861, 'duration': 8.563}, {'end': 965.706, 'text': 'so this is how we now can generate or create a user with a hashed password.', 'start': 959.424, 'duration': 6.282}, {'end': 979.078, 'text': 'now if we have the user here, then we can call user save to save the user in the database and then we can again chain then here.', 'start': 965.706, 'duration': 13.372}], 'summary': 'Code needs changing to execute bcrypt operation first, then create user with hashed password.', 'duration': 44.904, 'max_score': 934.174, 'thumbnail': ''}, {'end': 1021.466, 'src': 'embed', 'start': 991.466, 'weight': 2, 'content': [{'end': 1005.999, 'text': "we get back a result and there we probably want to return a response where we don't need to return even can just say response status with status 201,", 'start': 991.466, 'duration': 14.533}, {'end': 1015.543, 'text': 'because we created a resource, and then json where we could have a message where we say user created something like that,', 'start': 1005.999, 'duration': 9.544}, {'end': 1021.466, 'text': 'and we can also catch any arrows, of course, and in such a arrow case we can do what we always did.', 'start': 1015.543, 'duration': 5.923}], 'summary': 'Return response with status 201 and json message for resource creation, handling errors.', 'duration': 30, 'max_score': 991.466, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE991466.jpg'}, {'end': 1098.565, 'src': 'heatmap', 'start': 1021.466, 'weight': 1, 'content': [{'end': 1025.588, 'text': 'we can simply maybe log it to the console and return it.', 'start': 1021.466, 'duration': 4.122}, {'end': 1035.971, 'text': "so like this, and let's also log our user in the result in the success case to the console so that we can see what was created here and with that,", 'start': 1025.588, 'duration': 10.383}, {'end': 1040.051, 'text': 'if we save all of that, we got our user creation, the sign up route.', 'start': 1035.971, 'duration': 4.08}, {'end': 1047.374, 'text': "now let's test it and for that i'll go to my app.js file and in there i'll first of all import it.", 'start': 1040.051, 'duration': 7.323}, {'end': 1058.921, 'text': "so i'll import user routes by requiring dot slash api routes user.", 'start': 1047.374, 'duration': 11.547}, {'end': 1068.248, 'text': "so just like i do it for the other routes, and then i'll go down there and also forward any requests going to slash user,", 'start': 1058.921, 'duration': 9.327}, {'end': 1072.071, 'text': 'slash something to my user routes.', 'start': 1068.248, 'duration': 3.823}, {'end': 1075.313, 'text': 'with that setup we should be able to reach that route with a post request.', 'start': 1072.071, 'duration': 3.242}, {'end': 1076.574, 'text': "now let's try it out in postman.", 'start': 1075.313, 'duration': 1.261}, {'end': 1078.636, 'text': 'So here I am in Postman.', 'start': 1077.415, 'duration': 1.221}, {'end': 1082.719, 'text': 'I prepared my request, post request to slash user slash sign up.', 'start': 1078.976, 'duration': 3.743}, {'end': 1088.403, 'text': 'Now I need to attach a body, which is now not form data, but a raw body of type JSON.', 'start': 1083.32, 'duration': 5.083}, {'end': 1098.565, 'text': "let's create such a json body and if you have a look at our route, then you see we try to extract the email here and of course, whoops,", 'start': 1089.301, 'duration': 9.264}], 'summary': 'Developed and tested a user sign-up route, with setup for postman testing.', 'duration': 77.099, 'max_score': 1021.466, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE1021466.jpg'}, {'end': 1145.066, 'src': 'heatmap', 'start': 1122.851, 'weight': 0.9, 'content': [{'end': 1131.715, 'text': "let's hit send and i get an error because i need to set my header content type application json.", 'start': 1122.851, 'duration': 8.864}, {'end': 1140.462, 'text': "let's now try again, and now we get user created as a message here, and if we have a look at our terminal here, where we do log something,", 'start': 1131.715, 'duration': 8.747}, {'end': 1145.066, 'text': 'we see a user was created, and this is this random hash i was referring to.', 'start': 1140.462, 'duration': 4.604}], 'summary': 'Error encountered on sending due to missing content type; user created successfully, with random hash generated.', 'duration': 22.215, 'max_score': 1122.851, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE1122851.jpg'}, {'end': 1182.681, 'src': 'embed', 'start': 1156.771, 'weight': 3, 'content': [{'end': 1161.533, 'text': 'so this is now the user we created on our server.', 'start': 1156.771, 'duration': 4.762}, {'end': 1163.573, 'text': "so now we're able to sign users up.", 'start': 1161.533, 'duration': 2.04}, {'end': 1164.974, 'text': "there's one issue, though.", 'start': 1163.573, 'duration': 1.401}, {'end': 1170.856, 'text': 'if i were to send the same request again, so i hit send again, Then the user is created again.', 'start': 1164.974, 'duration': 5.882}, {'end': 1174.597, 'text': 'So now we created two users with the same email address.', 'start': 1171.456, 'duration': 3.141}, {'end': 1177.599, 'text': "And chances are that you don't want that.", 'start': 1174.977, 'duration': 2.622}, {'end': 1182.681, 'text': 'You want to ensure you only have a user with an email address once in your database.', 'start': 1178.319, 'duration': 4.362}], 'summary': 'Issue: duplicate user creation due to resend requests, leading to multiple users with the same email address.', 'duration': 25.91, 'max_score': 1156.771, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE1156771.jpg'}], 'start': 894.293, 'title': 'User creation and validation', 'summary': 'Covers creating a user sign-up route, implementing validation, and successfully creating a user with a unique email address while preventing duplicate user creation.', 'chapters': [{'end': 1021.466, 'start': 894.293, 'title': 'Handling hashed passwords in user creation', 'summary': 'Discusses a function for handling hashed passwords in user creation, where it checks for errors and stores the hashed password in the database using bcrypt, returning status codes and json objects as responses.', 'duration': 127.173, 'highlights': ['The function checks for errors and returns a response with status code 500 and a JSON error object if an error occurs. When an error occurs, the function returns a response with status code 500 and a JSON error object, providing a clear indication of failure.', 'The function uses bcrypt to hash the password and only creates a new user if the password is successfully hashed. The function utilizes bcrypt for hashing the password and ensures that a new user is created only if the password is successfully hashed, enhancing security and data integrity.', 'Upon successful user creation, the function returns a response with status code 201 and a JSON message indicating the successful creation of the user. In the case of successful user creation, the function returns a response with status code 201, signifying the creation of a resource, and a JSON message indicating the successful user creation, enhancing user experience and providing confirmation of the operation.']}, {'end': 1276.334, 'start': 1021.466, 'title': 'User creation and validation', 'summary': 'Covers the process of creating a user sign-up route, testing it using postman, and implementing validation to prevent duplicate user creation, resulting in the successful creation of a user with a unique email address and the handling of duplicate email requests.', 'duration': 254.868, 'highlights': ['The user creation process is demonstrated, resulting in the successful creation of a user with a unique email address. Successful creation of a user with a unique email address', 'The issue of creating two users with the same email address is highlighted, emphasizing the need for validation to ensure only one user exists with a particular email address in the database. Creation of two users with the same email address', 'The process of implementing validation to prevent duplicate user creation is explained, involving the use of the user model to search for existing user entries with a specific email address and returning an appropriate response status code (409 or 422) based on the outcome. Implementation of validation to prevent duplicate user creation']}], 'duration': 382.041, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE894293.jpg', 'highlights': ['The function utilizes bcrypt for hashing the password and ensures that a new user is created only if the password is successfully hashed, enhancing security and data integrity.', 'The function checks for errors and returns a response with status code 500 and a JSON error object if an error occurs, providing a clear indication of failure.', 'Upon successful user creation, the function returns a response with status code 201 and a JSON message indicating the successful creation of the user, enhancing user experience and providing confirmation of the operation.', 'The process of implementing validation to prevent duplicate user creation is explained, involving the use of the user model to search for existing user entries with a specific email address and returning an appropriate response status code (409 or 422) based on the outcome.', 'The issue of creating two users with the same email address is highlighted, emphasizing the need for validation to ensure only one user exists with a particular email address in the database.', 'The user creation process is demonstrated, resulting in the successful creation of a user with a unique email address.']}, {'end': 1730.815, 'segs': [{'end': 1325.62, 'src': 'heatmap', 'start': 1299.77, 'weight': 0.798, 'content': [{'end': 1306.553, 'text': 'so that is where we should then try to hash our password and do all our other stuff.', 'start': 1299.77, 'duration': 6.783}, {'end': 1316.617, 'text': "so i'll cut this and put it into this else block here, just to make sure that we only execute this if we don't have a user for that email address.", 'start': 1306.553, 'duration': 10.064}, {'end': 1325.62, 'text': 'and now, if we save this all and i send the same email and password combination again, i get the mail exists error, and if i send a different one,', 'start': 1316.617, 'duration': 9.003}], 'summary': 'Implementing password hashing to prevent duplicate email and password combinations.', 'duration': 25.85, 'max_score': 1299.77, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE1299770.jpg'}, {'end': 1406.532, 'src': 'embed', 'start': 1328.682, 'weight': 0, 'content': [{'end': 1335.826, 'text': 'Why? Because remember, if you use user find like this, user here is actually not going to be null.', 'start': 1328.682, 'duration': 7.144}, {'end': 1339.148, 'text': "If you don't find entries, it's going to be an empty array.", 'start': 1336.387, 'duration': 2.761}, {'end': 1344.992, 'text': 'So instead, what we should check here is if user length is greater or equal to one.', 'start': 1339.709, 'duration': 5.283}, {'end': 1348.033, 'text': 'That means we already have that email address.', 'start': 1345.552, 'duration': 2.481}, {'end': 1352.995, 'text': 'And for other lengths, like zero basically, we want to create a new user.', 'start': 1348.333, 'duration': 4.662}, {'end': 1359.478, 'text': 'So now if I save this and set this again, we create the user, but if I send it a second time, we get mail exists.', 'start': 1353.375, 'duration': 6.103}, {'end': 1361.899, 'text': 'So now this is working as it should.', 'start': 1359.998, 'duration': 1.901}, {'end': 1370.542, 'text': 'obviously we now have the issue of having one wrong user entry in our database because we created that first email address twice,', 'start': 1362.779, 'duration': 7.763}, {'end': 1373.283, 'text': 'or maybe you pressed the button more often.', 'start': 1370.542, 'duration': 2.741}, {'end': 1376.064, 'text': 'so we will also need to clean that up.', 'start': 1373.283, 'duration': 2.781}, {'end': 1378.004, 'text': 'and how can we clean it up?', 'start': 1376.064, 'duration': 1.94}, {'end': 1386.808, 'text': 'well, we can simply add a delete route here which allows us to also delete users, something we probably want to you have in our application anyways.', 'start': 1378.004, 'duration': 8.804}, {'end': 1390.269, 'text': 'so now i will add a delete route here.', 'start': 1386.808, 'duration': 3.461}, {'end': 1406.532, 'text': "i'll just have slash user id and get my request response next function here and in there.", 'start': 1391.403, 'duration': 15.129}], 'summary': 'Checking user length to create or find user, need to handle duplicate entries and add delete route.', 'duration': 77.85, 'max_score': 1328.682, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE1328682.jpg'}, {'end': 1571.731, 'src': 'embed', 'start': 1539.03, 'weight': 1, 'content': [{'end': 1543.033, 'text': "I now got a functionality to get rid of that user, which I don't need.", 'start': 1539.03, 'duration': 4.003}, {'end': 1546.215, 'text': 'So with that, we also got the delete route.', 'start': 1543.953, 'duration': 2.262}, {'end': 1550.437, 'text': 'We check if a user email exists before we try to create a new user.', 'start': 1546.615, 'duration': 3.822}, {'end': 1560.984, 'text': "One more thing we should do is we should go back to the user model and for the email I'll add another configuration which is unique,", 'start': 1550.978, 'duration': 10.006}, {'end': 1562.085, 'text': 'which I also set to true.', 'start': 1560.984, 'duration': 1.101}, {'end': 1571.731, 'text': 'now. this can be really deceiving and and strange, because you could expect that by setting unique, you can basically save this code here.', 'start': 1562.685, 'duration': 9.046}], 'summary': 'Implemented functionality to delete user, added email uniqueness check.', 'duration': 32.701, 'max_score': 1539.03, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE1539030.jpg'}, {'end': 1629.845, 'src': 'embed', 'start': 1604.185, 'weight': 2, 'content': [{'end': 1612.671, 'text': 'Speaking of validation, one more thing we can do, though, is we can add another config here to email the match config.', 'start': 1604.185, 'duration': 8.486}, {'end': 1615.433, 'text': 'If type is string as it is here,', 'start': 1613.352, 'duration': 2.081}, {'end': 1625.601, 'text': "you can add some other built-in validation shipping with Mongoose and you can match that incoming string to a given pattern to ensure that what we're storing really is an email address.", 'start': 1615.433, 'duration': 10.168}, {'end': 1629.845, 'text': 'So first of all, distribute this over multiple lines to make it a bit easier to read.', 'start': 1626.201, 'duration': 3.644}], 'summary': 'Demonstrates adding email validation config using mongoose for string type.', 'duration': 25.66, 'max_score': 1604.185, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE1604185.jpg'}, {'end': 1659.8, 'src': 'heatmap', 'start': 1630.465, 'weight': 0.716, 'content': [{'end': 1634.089, 'text': 'And then we need a regular expression for validating email addresses.', 'start': 1630.465, 'duration': 3.624}, {'end': 1645.727, 'text': 'Now, as all pro developers, we can simply Google for email regex to find this great email regular expression discussion thread on Stack Overflow.', 'start': 1635.717, 'duration': 10.01}, {'end': 1652.393, 'text': "And there, if you scroll through, you'll find this great answer here, where we got a couple of demo validation patterns.", 'start': 1646.247, 'duration': 6.146}, {'end': 1655.877, 'text': "And I'll use this one, which should match most cases.", 'start': 1652.633, 'duration': 3.244}, {'end': 1659.8, 'text': 'Email address validation with regular expressions is pretty hard, as it turns out.', 'start': 1656.217, 'duration': 3.583}], 'summary': 'Using a regular expression for email validation from stack overflow, which should match most cases.', 'duration': 29.335, 'max_score': 1630.465, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE1630465.jpg'}], 'start': 1276.334, 'title': 'Handling user existence and cleanup process', 'summary': 'Discusses ways to handle user existence in the database, including conditional checks for email existence, and the need for a cleanup process to remove duplicate entries. additionally, it introduces adding a delete route for users and implementing user validation in the user model, along with unique and match configurations and regular expression for email validation.', 'chapters': [{'end': 1378.004, 'start': 1276.334, 'title': 'Handling user existence and cleanup process', 'summary': 'Discusses handling user existence in the database, using conditional checks to determine if the email exists, and the need for a cleanup process to remove duplicate entries.', 'duration': 101.67, 'highlights': ['We should check if user length is greater or equal to one to determine if the email exists, and for other lengths, like zero, we want to create a new user. Using conditional checks to determine if the email exists by checking the length of the user array and creating a new user if the length is zero. This ensures proper user existence handling.', 'The need for a cleanup process to remove duplicate user entries in the database. Discussing the need for a cleanup process to remove duplicate user entries in the database, addressing the issue of having one wrong user entry and the importance of cleaning it up.', "Explanation of how 'user' behaves when finding entries, where 'user' is an empty array when no entries are found. Clarifying how 'user' behaves when finding entries, highlighting that it becomes an empty array when no entries are found, providing important insight into the behavior of the 'user' variable."]}, {'end': 1730.815, 'start': 1378.004, 'title': 'Adding delete route and user validation', 'summary': 'Introduces adding a delete route for users and implementing user validation in the user model, along with the unique and match configurations and regular expression for email validation.', 'duration': 352.811, 'highlights': ["Implemented a delete route to delete users by their ID, setting up response messages for successful deletion and error handling for failed deletion. The implementation of the delete route allows for the deletion of users by their ID, with a detailed handling of successful deletion and error responses, enhancing the application's functionality.", 'Configured the user model with the unique configuration for email, optimizing the field for search and indexing without adding validation. The unique configuration for the email field optimizes it for search and indexing, although it does not add validation, providing insight into the functionality of the unique configuration.', 'Added a match configuration to the email field in the user model, utilizing a regular expression for email validation. The addition of the match configuration with a regular expression for email validation enhances the data validation process for the email field in the user model.']}], 'duration': 454.481, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/_EP2qCmLzSE/pics/_EP2qCmLzSE1276334.jpg', 'highlights': ['Implemented a delete route to delete users by their ID, setting up response messages for successful deletion and error handling for failed deletion.', 'Configured the user model with the unique configuration for email, optimizing the field for search and indexing without adding validation.', 'Added a match configuration to the email field in the user model, utilizing a regular expression for email validation.', 'The need for a cleanup process to remove duplicate user entries in the database.', 'We should check if user length is greater or equal to one to determine if the email exists, and for other lengths, like zero, we want to create a new user.']}], 'highlights': ['JSON web tokens provide secure access to resources and avoid the use of sessions.', 'The function utilizes bcrypt for hashing the password and ensures that a new user is created only if the password is successfully hashed, enhancing security and data integrity.', 'The process of implementing validation to prevent duplicate user creation is explained, involving the use of the user model to search for existing user entries with a specific email address and returning an appropriate response status code (409 or 422) based on the outcome.', 'Implemented a delete route to delete users by their ID, setting up response messages for successful deletion and error handling for failed deletion.', 'Setting up User Routes: Emphasizes creation of user routes for sign up and sign in', 'The chapter covers the process of implementing authentication in a RESTful service with Node.js.', 'Explains the significance of understanding how authentication works in a RESTful service.', 'The need for a cleanup process to remove duplicate user entries in the database.', 'The function checks for errors and returns a response with status code 500 and a JSON error object if an error occurs, providing a clear indication of failure.', 'Configured the user model with the unique configuration for email, optimizing the field for search and indexing without adding validation.']}