0:01
We are now going to take the steps to integrate the Angular client
that we have developed in the previous course, and
the Ionic client that we developed in the Ionic course
earlier with the REST server that we have just developed.
So continuing on with the REST server that we developed in the previous exercise,
we're going to make some adjustments to the server side first,
in order to facilitate the communication between the client and the server.
Now in this case, the adjustments to the server side are fairly minimal,
as you will see.
We will keep certain routes open so that our client can still display some
of the information without requiring the user to log in.
But for displaying other pieces of information,
we will expect the user to log in to their system.
So for example,
if you have displayed the favorites of the user, you may expect the user to log in.
Whereas, if you just want to show the menu items to the user,
then it shouldn't really matter.
You should be able to see the menu information,
even without logging into the system.
So, minor adjustments like that will be made first to the server side.
And then I will show you the corresponding client side implementation
that interacts with this REST server, including user authentication.
1:35
One of the few things that we're going to do on the server side is first to keep
the get operations on the REST endpoints open for users.
Typically when the user tries to get information from the server
in order to display information in the app or
in the dev application, then you should allow them to do so.
Modifications to the information would require authentication.
So for example, posting of comments, or, for
example, adding some of the dishes to your list of favorite
dishes will require you to be logged in to perform those operations.
So on the server side, we have pretty much done everything that we require.
All that I'm going to do is to adjust the get routes for all the different
routes such that those can be handled without requiring user authentication.
In addition, we saw earlier that on the front page of our web application or
the index page, the homepage of the web application or
the home screen of our Ionic application,
we were showing the list of featured dish that
featured a promotion and featured leader.
So, to help us facilitate that, what I'm going to do is to introduce
3:24
retrieve only those records that have been marked as featured items there.
So that's one other adjustment that I'm going to make to the server side.
So, let's go ahead and make those adjustments, and
then we'll come back and look at how the server supplies the information.
So here I have our REST server open in Visual Studio Code.
I found that Visual Studio Code is very well suited for doing node applications.
So, that's why I switched to Visual Studio Code for
doing the server-side applications.
You can also use Visual Studio Code even for client-side applications,
but I find that Brackets was doing a good job on the client side.
So I'll stick with that for the client-side applications.
For the server-side, I pretty much have become a fan of Virtual Studio Code now.
So this is Visual Studio Code 1.1, the latest version that I am using here.
So in here, in the models folder, you can see that I have the dishes
open and the schema for the dishes being displayed here.
So, into this schema in the dishSchema, for example,
at the bottom, after the price, I'm going to add one more item,
called as featured, which will be a Boolean flag there.
5:01
will be by default set to false.
But if I want this particular dish to be featured on the front page of
my application, then I would set a Boolean flag to true.
I could have more than one dish if I so choose to.
In that case, I would have to have some kind of a way of showing
multiple featured items of each kind on my front page.
Currently I am displaying only one item, one dish, one promotion, and
one leader on the front page.
But I could easily use the carousel for
displaying multiple featured items on the front page.
So, what I'm going to do is to add the featured field to their dishes schema.
Same thing for promotions and also for leadership,
I'm going to add this featured flag there.
So for dishes, I have added a feature flag.
I am going to do the same thing with leadership.
Also with leadership here I am going to add in the featured flag there.
And for promotions also,
I'm going to add in the featured flag there,
and by default that would be set to false.
So if you do not specify the featured flag when you are inputting an item,
adding an item to the server, then that will be by default set to false.
You can set the featured flag to true later on if you so choose to.
So these changes to the models, I'm going to save.
Now, once we have made these changes to the models,
the routes will have to be adjusted.
Such that when you do a get operation, then from the client side,
you could send in a request saying that,
send me back only those dishes or those promotions or
those leaders whose featured flag is marked to true.
So, that is a query that I can send from the client side,
and then the server would be expected to return only a subset of those for
which the featured flag is set to true.
By default, it can set only one of them to true, so
that only one item would be returned.
But the query will return an array of items.
So, that is something that you need to keep in mind when you're adjusting
the client side application.
7:37
Let's now proceed ahead with making changes to the dishRouter.js file.
The same changes I would make even for
the leaderRouther.js file and the promoRouter.js file.
I will show you the changes for the dishRouter.js file.
File I would suggest that you apply the same changes, also to that and that.
So, first thing, for the get operation on the dishRouter.route slash,
which is the slash dishes route, I will remove the user authentication.
So I will delete the verification there.
In addition, as you realized in the schema,
we introduced this flag called featured,
which when set to true will return all the users.
Now when we do the Dishes.find in the get,
currently we were using Dishes.find with
the empty JavaScript object there.
Instead I am going to use that req.query in place of that.
Now what does this mean?
If my request that is coming in from the client
side includes the information in the query,
as you will see when I explain the use of this later on.
9:14
That information, when it is decoded by my express.Router,
will load any information that I include in
the query string into the req.query object, or
rather the req.query property of the req, request object coming in.
So I am just going to use the req.query and
then directly do a find on the dishes in there.
So in this case, then if I include in my rest api URL
the feature equal to true, as you will see later,
then that will literally result in this get
request sending back only those dishes for
which the featured flag is set to true.
So in here I am adjusting by simply using the req.query
directly in the Dishes.find method here.
So that way it'll retrieve only those for
which suppose I don't include the query string in my rest api URL.
Then the req.query will be empty, which would be an empty JavaScript object.
And that is what will result in fetching all
the items from the dishes document array in my database.
So, that works perfectly fine in that circumstance too.
10:52
So, making this adjustment to the dishes, we'll now proceed ahead.
Now, one additional thing that I would like to do is
wherever I have an if (err), instead of throwing the err,
I will simply call next with the err as the parameter.
So this way, my error handler in the app.js file that
we have already included will take care of handling the error.
So as you can see, this if (err) I'm going to
update that from throw err to next (err) and
include that err inside the brackets for the next.
I will apply this throughout for
all the cases where I am having this if (err) statement there.
Instead of throwing the error, I'm going to do next (err) so
that my server does not crash when it encounters an error.
11:50
Similarly, when I do a get for the specific dish, even the get route for
the specific dish, also, I'm going to remove the authentication.
So, I'm going to remove the verifyOrdinaryUser from the get
request for dishRouter, dishId there.
Also continuing on for any circumstance when I
encounter the if (err) with throw error,
I'm going to replace each of them with that next (err).
In addition, for the dishId/comments route, I'm going to remove this all
verifyOrdinaryUser, that is going to cause more problems than what I anticipated,
so I'm going to remove that completely and instead control individual routes.
For the get operation on the comments,
we're going to leave it open because when a dish is being displayed, then we
want to show all the comments about the dish that have been posted by all users.
So the get will be left as open.
For the post operation for comments, then I would expect
the user to be logged in, so that's why I will verify that
the user is logged in before I allow the user to post a comment.
Because when the user posts the comment, we do expect the user’s
information to be automatically captured on the server side,
note that the user is being authenticated using the token that comes in the header.
So, from that I'm going to decode the user ID automatically.
So, that adjustment I'm going to make here.
13:37
In addition, for the req.body, remember that
the req.decoded._doc._id was the one that was carrying the ID of the user.
Now I'm going to adjust my users.js
file such that instead of including the entire information about the user,
I'm going to include only the user name, the ID, and
the admin flag so that my token size is now reduced.
I don't need to carry the entire information about the user in my token.
Instead I will cut it down to just the bare essentials that I need for the user.
So when I do that, then my req.decoded will no longer contain _doc.
Instead it'll directly contain the _id.
So I'm going to adjust this particular line
from rec.decoded._doc to simply req.decoded._id.
So this is one more adjustment that I'm going to make here.
Similarly, any place where you were using req.decoded_doc._ id,
change that by removing the _doc.
For deleting all the comments, now because my
comments route is left open, so for the delete,
I will make sure that the user is a valid user.
In addition, all the comments can only be deleted by an admin.
So that's why I have the verifyOrdinaryUser and
verifyAdmin, one following the other in the delete operation there.
So that's one more adjustment that I'm going to make for
the delete of the comments.
15:30
Similarly, for a specific comment,
I will still expect the user to be logged in.
So I'm going to remove the all route from the dishRouter for
the specific comment, and instead for the get operation,
I will expect the user to be authenticated.
So that's why for the get operation, I added the verify OrdinaryUser.
For the put operation also, similarly,
I will add the verifyOrdinaryUser for the put operation.
Now in the put operation, again, note that the req.decoded needs to be adjusted.
So I'm going to remove the _doc from there, and
then simply change the direct decode.
16:22
Similarly for the delete operation, also I expect the user to be logged in,
so that's why I'm checking the verifyOrdinaryUser.
And then inside there, I'm going to, again,
adjust the req.decoded from req.decoded._doc._id,
to req.decoded._id there.
With that, we complete the updates to the dishRouter.
17:05
And for the get request, req.query should be included in the .find for
the get request and the if error should
be adjusted to use next Error rather than throwing the error.
So those changes I would expect you to make to the later router and
the promoter.js files too.
So after we have made these changes we need to adjust the users.js file and
also the very file.js file.
17:37
Going to use a start JS file.
When we created the token earlier, when we requested for
the token we said, getToken user.
So we are processing the entire user body as a part of the request for
getting the token.
Instead, I'm going to select only certain fields from the user
18:09
including only the username which I retrieved from user.username.
Then the ID which is set to user._id.
And the admin flag, which is set to user admin flag.
Only these three I will pass in when I create the token.
So that way my token size will be
significantly smaller compared to the previous implementation.
So with this change let's save the changes.
Now when we do this change, even in verified RJS when we verify the admin
value, we again need to make sure that we are only checking the right things there.
So going to verified RJS file In the verify admin function,
earlier we had req.decoded._doc._id.
So we're going to remove that _doc because that is no longer relevant here.
Same thing for the.
19:08
Admin flag, you're going to simply change this value from
req.decoded_doc.admin to just req.decoded.admin because the admin
flag was explicitly past tense when we created the token in user start GS file.
So with this changes,
now your server is ready to take on request from the client sites.
So after these modifications, your server is now ready to go forward for
implementing your integration with the client side.
19:57
Now my server is up and running.
So, let me send a get request to our local host 334/dishes.
As you see in the headers, I currently have nothing in the headers,
so, which means I am sending a request without having a token there.
So when I send the get request,
obviously I am getting the information from the servers with all their
20:23
id and other fields for the dishes included.
In particular note that in the reply there is an extra field there called feature
which is either false or for one of the dishes the features will be set to true.
So in this case you can see that
one of the dishes has the featured flag set to true.
So now, if I instead of sending the get request to that,
instead if I include in the header Featured equal to true.
So when I send a get request to the URL question mark feature equal to true work.
I am indicating is the parameter that i am sending in to the silver sock.
So when I do that on the silver side, when this URL gets parsed,
then this featured equal to two will be turned into a JavaScript object and
Will be available to us on the server side as rec.query.
The rec.query will become equal to featured:true,
which is the equivalent JavaScript for
this query parameter that we are sending here.
So when I do that with the feature equal to two, then you would notice that
only one item has been returned to me The particular item for
which the featured flag is set to true.
And also notice that this is now an item inside an array.
So that's another important thing that we need to
note about the insert feature dish.
Same thing even to sending requests to leadership and promotions.
Now I am sending a request to promotions, so
in this case also you would notice that the item
that is returned will have the featured flag set to true in this case.
So this is the other, a change that we
22:59
promotion and a single leader featured on the page.
So using this featured flag,
we are able to retrieve only that particular item from the server site.
Previously we were accessing this using the index value,
which is not the right way of doing on the client's side.
So that's the reason why I made this modification to my server side.
So that from the client's side I can send in the request for only those items For
which the feature set to true.
23:36
Now, the user log in works just like before.
You can log in the user by posting to the local host 3443 user login.
And then you will see that the login is successful, and the token now return will
be much smaller in size because we are only including the username ID.
And admin fly Inside the token rather than the entire user document.
So that's the reason why this is a lot more efficient way of handling the token.
Because we only need those three items for our Server side application.
So with this, we complete our modification of the server side.
We will now move on to consider how we can design the client side application.
Obviously, if you have taken the angular JS course and the ionic course earlier.
You've already seen the development of their client side application there.
Now the client side application that I am going to present to you
would be a slightly modified version of that,
which operates much better with this server site.
24:51
So even though much of the code will look similar to what we
developed in the previous courses,
some code needs to be adjusted in order to interact with the server site.
In addition we'll also be handling user authentication and
user registration with the client side.
So I will provide you the completed client side code and then explain the salient
features of the client side code in this lesson in the next exercise.