0:03
In the previous exercise,
we have seen how easy it was for us to configure and then
scaffold out a recipient server using the LoopBack framework.
We see that this LoopBack framework supports an entire spectrum
of the recipient endpoints and
all the operations of the recipient endpoints automatically for us,
when we scaffold out our application.
In this exercise, we will look at how we can connect
our LoopBack server to a back-end database,
or MongoDB in this instance,
and we'll also see how we can set up various access controls on the recipient endpoints.
So using the access controls,
we can specify what kind of operations can be carried out on the recipient endpoints,
and who will be allowed to carry out those operations.
So for example, an unauthenticated user or a guest can only
access information or do a get operation on the recipient endpoints,
an authenticated user would be able to also do the same,
but only an administrator would be able to write data into my server.
So, any put, post and delete operations can only be carried out by an administrator.
Along the way we will also see how we can set up an admin account in our LoopBack server,
and then configure it so that
only the admin user will be allowed to perform these operations.
So this is where LoopBack allows us to define something
called roles associated with various users.
So each user can be assigned a role.
As an example, you can talk about an ordinary user,
an administrator, a super admin and so on.
So you can subdivide your set of users into various groups,
and then assign various roles to them.
Also we will look at how the built-in user model can be further customized,
within our LoopBack application,
and how we can build another model on top of the user model,
and then use the user model as the base class
and develop a higher level model called the Customer Model,
which allows us to store additional information for each
of the customers that will login to our site.
So, let's explore some of these features of LoopBack in this exercise.
To get started on this exercise,
the first thing that I would like you to do,
is to start up your MongoDB server.
So here I am in another terminal tab in my MongoDB folder,
where I configured my MongoDB server earlier,
which was used by my Express Plus MongoDB server in the previous exercises.
So let me start up the MongoDB server by typing
MongoD minus D-B part data
in this folder and then start up my MongoDB server.
Now, I'm going to connect my LoopBack server to my MongoDB server.
So going into my LoopBack server folder here,
I've to prompt type L-B data source.
This will allow us to configure the data source for our LoopBack Server.
LoopBack itself can simultaneously connect to multiple data sources if you so choose to,
and it supports various kinds.
It supports My Cycle databases, it supports MongoDB,
it supports Cloudant which is also another document database,
it supports Oracle, and many other kinds of databases.
So, you can easily configure that.
In this example, I'm going to configure my LoopBack server
to talk to my MongoDB in the back-end.
So at the prompt,
if we type L-B datasource,
it'll prompt us for information.
So first thing it'll ask us is for the datasource name,
and then I will configure this datasource name as MongoDB,
and then it'll prompt me to select the connector.
LoopBack uses connectors to connect to various databases behind the scenes.
So as you can see, the in-memory DB which is the one that
they just used in the previous exercise,
but of course the in-memory DB means that once you shutdown your server,
all the values will be gone,
and so that is not a persistent data storage.
So here you see the various kinds of databases that StrongLoop supports here.
So you can see the long list of the various databases that are supported.
So you can see that it supports Cassandra, Redis,
we had briefly referred to these when we talked about noSQL databases, MongoDB,
My SQL, PostGres, Oracle,
and even directly to other Rest API servers to SOAP servers,
Coachbase and so on.
So you see that it provides us with
a long list of various kinds of data sources from there,
our LoopBack server can read in information.
In my case, I am going to use the MongoDB server so I
am going to set up the MongoDB connector.
So when I do that,
LoopBack will automatically install the MongoDB connector for us,
and when it asks for the connection string URL,
we'll just leave this as empty because we will allow
it to use the standard way of configuring.
When it asks for the host we will say
localhost because we are running our MongoDB on the same computer.
Otherwise, you will specify
the hostname of the computer on which you are MongoDB is running.
Then the next one is the port number and we are
using our standard MongoDB port number 27017,
and it will also ask for the username and password if required,
and right now my MongoDB is running without having to
do any authentication so I leave the username and password empty,
and the database name.
The database name on the MongoDB server that is running behind the scenes,
the database name there is confusion.
If you recall that's the database name that they have set up on our MongoDB server.
And then it'll ask us whether it should install the LoopBack connector,
and I will say yes,
and will actually go ahead and install the NPM module which access
the LoopBack connector to the MongoDB database.
And once that is done,
my Loopback connector is installed here so you can see that this is version 1.18.1
and my LoopBack server is all ready to talk to my MongoDB.
Now before I proceed forward,
in the previous exercise I don't really configure some models
and then I specify them to be stored in the DB,
I will need to go and update them to store their data in my MongoDB.
So, let's go and quickly reset our code for the LoopBack server.
This also provides us with an opportunity to look at
what my Loopback server itself has configured in this folder.
Opening the LoopBack folder in our editor,
you can see that Loopback has already
scaffold out a whole bunch of files into this folder.
The package.json of course contains
all the related NPM modules that have been configured out here,
and in here you can see that LoopBack itself has configured out the LoopBack NPM module,
the LoopBack boot module and in
particular let me draw your attention to the LoopBack MongoDB connector,
that we had just installed a short while ago, and many others.
In particular the configuration for the Loopback server is all
stored mostly in Json files here,
with additional javascriptcore whenever required.
We'll look up the javascript code customization a little bit later.
Let me draw your attention to this folder called common.
In this common folder,
you will see all the models that we have configured out earlier.
So you'll see that we have the dishes.Json files.
So when you open the dishes.json file, you see how LoopBack
stores all the information about the dishes model that you had just created,
so it has the name, the base,
and some other values here that it requires.
And then look at the properties and how all the properties are stored in here.
So you see some things that are very easy for you to
recognize they're in the dishes.json file.
Similarly, the leaders.json and the promotions.json.
The dishes.js file is big,
we can add in some additional customization code for the dishes,
but right now we're not going to do that,
and so we'll just leave it as is.
So this is where you can add in some additional code that may
need to be executed when you access the slash dishes end point.
But right now we are going to be leaving it blank for the moment.
Now let's also look at the server folder here.
And the server folder,
in particular let me draw your attention to the datasources.json file here.
In the data sources.json file,
all the different data sources will be configured here.
So right now, we only have the DB which is
the in-memory DB database that LoopBack by default configures,
and then the MongoDB which we just configured,
only absorbed the information that the input has
been stored into that datasources,json file.
So, you'll see that LoopBack itself operates by configuring all these files
which the LoopBack framework itself makes use of when it
starts up the LoopBack-based rest API server.
Let's go into the model config.json file here.
The model config.json file itself
stores a lot of information here which is useful for us,
but in here, let's go in and modify a few things.
So into this, we will see that there're again for the dishes,
promotions and leaders, the data source has been configured as DB.
So we are going to modify that to MongoDB here.
Not only for this one,
they'll also change that for promotions, and also leaders,
meaning, that all these three will derive their data from the MongoDB.
Also, for the Role that is defined here.
We'll also store in MongoDB.
We'll pretty soon see how we'll make use of the Role,
and also the RoleMapping here.
We'll understand the reason for these two in a short while.
And then, ACL, the Access Control Lists,
these will also be stored in MongoDB.
And then, the user, also,
we will store it in MongoDB,
and then they will leave it there.
So, these are the modifications that you should do to
the model-config.json file and then save the changes.
As I mentioned earlier, Loopback by default,
supports this model called, user,
which is used for supporting user authentication.
The user model itself stores only three different properties.
The user name, the email address,
and the password related information.
Now, if they want to have
a more elaborate way of storing additional information about users.
Then they can subclass this user-base model,
and then make use of that.
So, in this next step,
I'm going to create another model called, the customer model,
which will use the user as the base model for its functioning.
And the customer model itself will store additional information about users.
So, in the customer model,
I will store the things like the first name,
the last name, and the image for the user and so on.
So, the customer will act exactly like the user model,
which already comes with its own set of the methods.
And so the user model is used for the user authentication,
so you can type in the username and password,
and log in and log out.
So, when we created this customer model based upon the base class of the user model,
the customer model will also support the log in and log out
operations in using this customer model.
So, we can log in the user and log out the user and so on.
So, the user authentication automatically comes for the right.
So, to create the customer model, at the prompt,
type lb model and for the model name,
we will type Customer.
And the dataSource, I will choose it as MongoDB.
And then when it asks for selecting the model's base class,
instead of using the PersistedModel,
we will move down,
and then select the User as the base class.
So, that way, it'll derive all their properties
of the base user class that is already built into Loopback.
And then we will expose this with the REST API,
and the custom plural MT.
And then this would be in the common folder.
And for this, the three properties that we will add are,
first name, which would we have the types string.
And this is not required or doesn't have a Default value.
And then, last name again as the type string,
not required, and no Default value.
And then image of the type string,
not required and no Default value.
So, you see that the customer class itself
carries additional properties in addition to the user class.
the user class already supports the user name,
the email and the password related information in there.
So, the customer class,
since sub class is the base class,
we'll get the user name and the email automatically from the user class.
And now, when you go to the model-config.jason file,
you will see that the Customer model has already been added in there.
And then in the common models,
you'll now see the customer.json file added in there
with these three additional properties that we have added to the customer model.
But note, that it specifies the base as the user class for the customer model here.
So, that's how Loopback allows you to take
a base-model class and then subclass that into the model class.
So, you'll see how Loopback enables us to automatically support user authentication using
the user class and then allows us to even define additional subclass of that,
which will store additional information related to the user-base class.
Next, we will set up Access Control for
the various models that we have already set up in our Loopback server.
So, to set up Access Control,
or the Access Control Lists in Lookback.
Loopback uses these Access Control Lists as a way of specifying what kind of
operations can be performed on
the different REST API endpoints are corresponding with the different models.
So, to do that, we'll type at the prompt lb acl,
ACL stands for Access Control Lists.
And then, when this run out, we'll say,
which model we want this Access Control List to be applied to.
And then we'll say, all existing models.
And we'll say, All metrics and properties.
And we will say,
All types of operations.
And then, we'll say, All users.
And then we'll say, Explicitly deny access.
So, we are first closing off all the models for everything,
then we will slowly open up,
whatever operations that can be performed by different users.
So, first step, we have closed off
all the types of operations on all the models that we currently have.
Then, we will slowly start opening each and every of the operations, step by step.
Now, the next step,
what we will do is again set up the next Access Control List.
In the second Access Control List, we'll say,
for all existing models and we'll say,
All metrics and properties.
And then, we will say, only Read access.
Meaning, when the user can perform the GET operations on these end ports.
And these GET operations can be performed by all users.
So, users can retrieve information.
And we'll explicitly grant the access for this.
So, which means that GET operations are allowed on the REST API endpoints node.
First, we closed off everything,
then we opened only the GET operations for the users.
Now, finally, they will go to each one of the models,
and then close off and allow certain operations only to
be performed by certain kinds of users.
So, to do that,
the next ACL that we will set up is for a specific model.
So, we'll set up this one for dishes.
And we'll say, A single method.
And then the method name is, create.
So, meaning that creation of these will be only allowed by.
So, again, when it say select the role,
then for the role, we'll say, other.
And then the role name would be admin.
So, what we're doing by this operation is that,
we are saying that only an admin user can create new dishes or update existing dishes.
So, this is a little bit close off, the remaining operations.
So, let's do the same thing for leaders.
And A single method and then,
the create and we will say,
only the admin can do this.
And then finally, also for promotions.
For promotions.
The single method, the create method will be allowed
only by users that have the designated role as an admin.
We'll see how we will create users with a specific role in the next step.
Explicitly grant access.
Now notice that I have not closed off customers for create operations.
If I close off customers,
nobody will be able to register into the system.
So, that's why I will leave that open.
Because, customer should be able to register into the system.
So, you can sign up for new accounts on the system.
User accounts on the system.
So, that will be left open for people to do.
So, to allow that for the customers, we'll say, customers,
A single method, create all users.
So, customers can be created by all users because that will
allow people to sign in to their account.
Finally, we will see how we can configure our server to start up
with a single admin user automatic configured into our Loopback server.
So, to do that,
in our Loopback server,
in the server folder we have this boot subfolder here.
Whatever code that we put in the boot subfolder,
will be executed at the startup of our LoopBack server.
So, in here, you'll see that we already have this authentication.js,
which is already set up,
a Loopback which will set up the user authentication for us.
And then we have the root.js which will set up
some additional information for our RAM Loopback server.
And we can add in additional files here.
So, I'm going to go in there into the boot folder,
and then add in this file called, script.js.
And in this script.js,
I'm going to set up the code to create an admin user by default.
So, in the script.js,
which will be nothing but a file-based NPM module so,
we'll start up by saying,
module.exports = function (app).
The app is the Loopback app,
which will be supplied as a parameter to this function for us.
And so, we can make use of it within our code here.
So, in here, we'll first set up a admin user.
So, to do that, we'll say,
var Customer = app.models.Customer.
So, this gives us access to the customer model.
Then we'll say, customers.findOne.
So, we'll first check to see if a user with
the username as admin is already configured in the system or not.
If not, then I'm going to create an admin user.
And this supplies me with a callback function with two parameters, err and users.
And inside this- So we'll first try to
see if a user with their name admin already exists.
If the user does not exist,
then we will create the user.
So, to create the user,
we'll say here, if not users.
So, if the users is not null or if the user says null,
then that means that there is no admin user so I need to create an admin user here.
So in this case, we'll say, customer.create.
And this create takes an array of objects if you want to.
And this array of objects will allow us to specify which user accounts we want to create.
So the first user account that I want to create or
the only user account that I want to create is the 'Admin'.
So this will be the default administrator for
my loopback server and then I can configure the email.
So recall that the user model supports these properties,
confusion.net and then password
I will configure as password.
You can also supply along with this,
the first name and the last name,
if you want, for the admin user.
But I'm going to leave it as such,
as empty because those are not required for the admin user.
So I'm going to leave it there.
So this command will end up creating a new customer with the name 'Admin'.
So if this user or the name "Admin" doesn't exist,
then we're going to create one.
And then in here we have the callback function.
25:45
So err users.
Now I will say,
if err, we don't know what it's trying to do so we'll just simply throw the err.
But normally we won't expect this to happen.
So now, how do you designate this user as an administrative user?
So right now when I sign up here,
I'm just signing up a normal user here,
but we want to give a special role to this user.
So that is where loopback supports a way of specifying roles for users.
So to specify a role,
we'll var Role = app.models.Role.
So this will allow me to create a role,
a new role call admin here.
So we can assign different drones to different users if you want.
And to together with this,
I also need to create a RoleMapapping here.
So we'll say, app.models.RoleMapping.
And if it so happens that the database already contains
any RoleMapping that already exists,
then I'm going to destroy all those when I start my server.
And then let me try to find
to see if a role with
that name admin already
exists in the system.
Okay.
And in this takes,
as you would expect,
a callback function and inside here we'll say, Role.findOne.
So if a role with the name admin already exist,
then I don't need to create one.
Otherwise, if that doesn't exist,
then I need to create the role.
So we'll say, Role.create.
So we'll create admin role here.
And then this takes us to parameters err,
role here, in the callback function.
Now again, here to handle the err,
we'll just copy this 'if err' and then paste it there.
Similarly here also, if the err occurs,
then I need to handle that.
So 'if err' then 'throw the err'.
Otherwise, we have created the role.
So now I need to map this role to this particular user that I have just create.
This user that I have just created up here.
This user. I want to give this user that role of the admin.
So since I've created this role by the name admin,
so we'll say, role.principals.create.
So this is how you create a mapping between the role and a particular user here.
So we'll say, role.principals.create.
So this is the syntax there.
We'll say, principalType: RoleMapping.USER
here and you'll take
a principal id here which is the users.
Now what does this user refer to?
This users refers to this that just came in.
So when we created this users,
then customer must create a successful return to us here.
So that is what I'm going to be using here.
We'll say, users[0].
So this would be an array of users that have been created and contain only one of them.
So that's why I'm saying user[0].
And then we'll assign ID of that user here.
So this is how we'll create a RoleMapping between the role that we have just created,
this role, and then map it to the customer that we have just created.
Now this also takes us to parameters, the callback function.
And in this callback function we'll just simply say,
if (err) throw (err).
Otherwise we are not really keen on knowing what else has happened there.
That's it. So this is how.
So if the role named admin doesn't exist,
we'll create that role.
If not- So this is the 'else'
part where I will still need to do this mapping.
So let me copy that code and then I will do exactly that here.
So role.principals.create and then map this for the user there.
So if the admin role already exists,
then all that they need to do is do the mapping.
So this will be stored in the RoleMapping model in our database. That is it.
So this piece of code that we put into the script.js file will first try to
find if an admin user exists and that user is identified by the name admin.
If not, then the user will be created and also then will create the role for the user.
We'll create a role named admin.
If that role exists,
then we'll just use that.
Otherwise we'll create the role.
And then after that we will create this mapping between the role and the user.
So loopback allows us to do the RoleMapping.
So saying this user is not to this role.
So this mapping is done by using this statement.
So that completes the setup of our servers.
So that an admin user will be created and that admin user will
automatically get the role of the admin as configured here.
That's it. Let's save the changes to script.js.
And now our loopback servers should be all ready.
So we'll now go and start our go back server and then check what we can do with this.
Going to the terminals,
let's start the loopback server.
So we'll say, npm start and then our server should be up and running.
Let's go to the Explorer and then browse the information there.
And this loopback server will have automatically
connected to my MongoDP because I have set up the connection.
Going to my browser,
let me reload this.
And when I reload this,
now you'll see that we have a new customer that has been created here.
The user already existed earlier.
The dishes, leaders, and promotions are all there.
Let's perform a get on the dishes.
Now that this is connected to the mouth MongoDB,
my MongoDB already have some dishes in there.
If your MongoDB is empty,
you can post some dishes using the post here.
So let's try it out.
When I do a get operation on the slash dishes,
you'll see that in the response body-
All the dishes that exist in my database have all been fetched.
Similarly, I can do a GET on
promotions and I should see the promotion that already exists in my database there.
So, you can see that the promotion already exists there.
So, that shows us how we can fetch information.
Now, let's try to post a new dish.
So, to post a new dish,
we go to the POST here.
Let me just copy this.
Obviously, at this moment,
because since I'm not a logged in,
I will not be allowed to post the dish so,
but I will demonstrate that to you are just copy and paste this information here,
and we'll try to post that dish,
and then when I try to post the dish,
my server immediately replies with this error saying, AUTHORIZATION_REQUIRED.
You are not authorized to do this operation.
So, that's why you are not authorized to do this operation.
Now, how do you authorize yourself?
So, to authorize yourself,
now recall that we have already created one user with the name admin,
and this admin user already exists as a customer here.
So, going into the customer's REST API endpoints,
if you scroll down,
down below here, you'll see this customer's log in.
So, when you do a POST on the customer's log in.
So, for the customer's log in,
you scroll up here and then here it asks for the credentials.
So, in the credentials,
we can type in username in double quotes, and we'll say,
Admin, and then password,
we'll say, password, and then we'll post this.
And then when you post it,
you will notice that in the reply,
LoopBack will send me back this information.
Now, within this information,
this particular id that it sends back is the accessToken for my LoopBack server.
So, I can just copy this accessToken here,
and then right at the top here,
you can see that this is Token Not Set, here.
It says Token Not Set.
And here you can type in this accessToken,
and then say, Set Access Token.
And then your accessToken will be set,
and then all subsequent operations that you perform will automatically carry
this accessToken in the header of my request message.
So, that way, now my admin will be allowed to do posts of items there.
So, now that I have logged in as an admin,
let me go to promotions,
and then I'll post one promotion there,
and show you that I can actually post promotions.
So, let's go to a POST,
and then we'll just copy this, and then in the data,
and then for the name we'll say, Test promotion,
and image we'll just leave it as such, description, Test Description.