4.2 Working With Models
In this lesson we’ll see how to add a user model with attribute validations to our application in order to store a collection of registered users. We can also install the
sails-mongo adapter in order to save users to MongoDB, and we’ll see how to use bcrypt to salt and hash users’ passwords for secure storage.
1.Introduction3 lessons, 11:27
2.Sails.js From the Front-End2 lessons, 20:07
3.Sails Blueprints2 lessons, 13:34
4.Building the Back-End7 lessons, 58:40
5.Additional Techniques2 lessons, 09:55
6.Conclusion1 lesson, 01:28
4.2 Working With Models
Hi folks. In this lesson, we're gonna take a closer look at models. We did create a model when we created the event API earlier in the course, but at that point, we focused on the blueprint routes that Sails created for us. So this time, let's focus on the model instead. In a real world scenario, we'd probably need to handle user registration and authentication. We'd want people to be able to sign in to see the dashboard. After all, it would be being used to monitor some other app. To keep the cause focused, we aren't going to worry about user registration. Let's just assume that users, probably members of staff, are entered into the database of allowed users via some other process. We will handle user authentication, however. So, we'll need to create a user model with attributes for username and password. So, let's go ahead and create the model now. So we use the generate Sails command, and we should see some feedback to say that it created the new API for us. So this will create the blueprint routes that we looked at earlier in the course, and it will also create the model behind the scenes, ready for us to start using, including creating a new configuration file called user.js in the api/models directory. We've also got an event file in there, from when we created the event model earlier on. At the moment, these files are pretty much empty. In the last lesson, we installed MongoDB, so let's now switch from Sails disc to MongoDB for our user model. To use a particular database with Sails, we need to install the appropriate adapter. We can do this from the command line via npm. So this should install the adapter for MongoDB and update our package.json file. Windows users may see some error output here, depending on the version of Note in use. The process should still complete successfully and we'll have what we need, so it's fine. So, now we need to add a new connection for Mongo. We can set ourselves about our Mongo database by adding a new connection for Mongo, which could be added to the connections.js file in the conflict directory. So, let's open up the connections.js file. And we should find that there are already examples for lots of common databases in here. If we scroll down, there should already be one for MongoDB. So we have one here called some MongoDB server, and it uses the adapter that we just installed, Sails-Mongo. And it runs on local host on port 27017, which is the default port used by MongoDB. So, let's just update the database configuration option. We'll just tell it to use a database called users. So now, we have to tell sails to use to use our local MongoDB server for our user model, so we can do this in the user.jsfile that sails just created for us. And we can do that using the connection property. Let's just update that. So we'll call that userMongodbServer, and we'll copy this into our user.js file. Great. So now, if we add a new user using one of these shortcut routes, we should find that it gets put into Mongo rather than Sails desk. So let's add the new record using postman. And we just need to make sure that our app is lifted. And I've got MongoD running in the background there as well. And it looks like there's some activity there, so hopefully Sails has already started to use Mongo for us. It's made the connection at least. So now, let's open up Postman. And this time, we want to use the user model instead of the event model. And we're gonna give a username and a password. And then, send that in and we should see a status of 201 and it should echo back the record that is just created. So now, let's have some attributes to our model, these attributes which are also known as a schemer are the user name and password, which we use to authenticate users in a later lesson. So, let's go back to Visual Studio now. And in the user.js file, we can add these attributes to the Attributes Objects. So we can specify that both fields are of the string type, and we should also specify that the username field should be unique. And that value needs to be a string. As we aren't going to be using the model to store new users, we don't need to worry too much about it. But, as well as specifying that model attributes should be unique, we can also specify defaults, automatically increment a numerical value or check that, for example, an email field is actually formatted as an email address. We'll want to specify that the user name and password are both required, and we can specify that passwords should be at least six characters in length. Great, so now, if we try to create a new user record without, either a user name or password, or one with a password of less than six characters, the request should be denied We also specified that the user name should be unique. And it looks like it's accepted that without any problems, whatsoever. Because we've made the change to the user.js file and that's in the API directory, we need to re-lift Sails before these settings are gonna take effect. So, let's just do that now quickly. And it looks like we've got an issue. So, there's an unexpected error and the reason why we've got an issue is because we just added that duplicate user name. So, let's just go back to Mongo, and let's see if we can get rid of that. So, what we're gonna do is, just grab the ID of the second record And we use the remove method and specify the object ID of the record that we want to get rid of. And now, we're back to having just the single record in our collection. So now, let's go back and try and lift Sails again. And this time, it starts it out without any problems. So now, the validations that we just added in user.js should work this time if we try tot add a duplicate user. We should see a message that we cant do that. So we see a validation error here, the attribute that's invalid is that we're missing the password and also it's triggered the min length, okay, because we didn't specify a password. And again, the password isn't long enough, so that's failed. So, the validations are working. We probably also wanna make sure that only attributes that we've specified in our schema are stored in the database. So we can do that easily using the schema option. And we just want to set our option to true. So now, even if we were to send extra data with the request to the create method only the user name and password fields would actually be stored in the database. So, we probably want to insure that we only store encrypted passwords in our database. We can use a node module called bcrypt to handle this for us. So let's get that installed via NPM. And once that's been stored, we then need to require this module in our user model. So in order to encrypt the password, we need to hook into the, before create event in our model. So that once the password is sent, Sails can then encrypt it, before it gets passed on to the database and stored. And this needs to be added after the attributes section. So, we add an event handler. And this event handler will be passed a user object and a callback. And we'll need to invoke the callback once we're finished. So for security, we want to generate a salt for when we hash the password. So we can do that, first of all. So we use the genSalt method, and the first argument is the number of rounds that the salt should be processed for, so we specify 10. And the second argument is a callback function, which is invoked once the salt has been created, and that will receive an error object and the salts. So now inside this function, we'll want to hash the password. And we can do that using another one of bcrypt's methods. And so it's quite the similar format to before, this time it's the hash method that gets used, and we pass it in several arguments. The first is the password that we want to hash, so that is the user.password. And that will be the password which is sent into the outer function from the user object. So that will be whatever gets sent, either via postman or however else we're creating the user. And the second argument is the salt to use when doing the hash, the third argument we just pass null there. And the last argument is another callback function. And again, this receives an error object as the first argument. And it receives the hash as the second argument. So, we can handle the error, if it exists inside our callback function. So if there is an error, we just log it out to the console, otherwise we replace the user.password with the new hash. And then, we need to make sure that we call the callback at the end. So before we can actually test this out, we want to go back to Mongo, and just remove the record that's already there. Now, we're back to having no records in our user collection. So now let's relift Sails again. And let's use postman again to create our user. So we use the same password that we used originally, just. Password and it's created it, but this time as you can see the password is a rather long hash instead of the word password. Great, so we should probably make sure that sense the value like the hash password isn't returned in the success response as well, so we can do that easily by overwriting the two JSON method in our. User model, so let's go back to Visual Studio again, and this time, we need to add the toJSON method inside the attributes objects. To inside the function that we are overriding cells is to JSON function with, this will point to the user record, so we can just set that to a variable good object. And we can then just delete the password field from that object. And at the end, we just need to return the new object. So, let's go back and remove our user one more time from Mongo. And now, let's go back to postman and send the request one last time. Actually, we probably want to relift Sails again, because we made a change to the users of JS file. So this time, in the response, we just see the username that was created and not the password. So in this lesson, we created a new model and saw how to add model attributes and attribute options such as specifying that a particular attribute should be unique or the type of the attribute. We also saw how to ensure that only data specified in our schema should be stored in the database, by setting the schema option to true. And, we configured our connection to MongoDB and so that in order to communicate with a particular type of database we just need to install an adapter for it. Lastly, we installed the bcrypt hyphen nodejs module. And used it to encrypt the password before saving it to the database, using the before create event hook inside our model. And we saw how to override the two JSON method to remove sensitive output from the response. Thanks for watching.