It's time to get started on the fourth and the final assignment of this course.
I have designed this assignment to be a consolidation
of everything that you have learnt in this course.
So this assignment will involve routing using the express router.
It'll involve the design of schemas in the model,
for our MongoDB and Mongoose,
and then also it'll look briefly at user authentication.
What exactly do we do in this assignment?
This assignment is based around the ability for a user to
save and retrieve a list of dishes as their favorite dishes on the server side.
If you had taken the previous courses of this specialization,
specifically the hybrid mobile app development courses,
whether it is ionic or native script,
you have seen that we have designed the apps to have the ability to allow the user to
save dishes in the list of their favorite dishes
and also retrieve dishes from that list of their favorite dishes.
When we implemented that in the previous courses,
we had implemented that using local storage on the specific device.
In this assignment, you'll be extending
the server side to be able to support exactly that.
This way, the user can save their list of favorite dishes on
the server side and access this list from
any device from which they will log in to their server.
What this means is that we need to design a new route for our server,
which we will call as the /favorites route.
On this route, we will have to design the express router to support the get,
post and delete operations on this route and
also design the schema to store the favorite dishes
and the corresponding Mongoose model and
connect the two together so that the information can be saved and retrieved from MongoDB.
We will also use the Mongoose population in order to draw in the information from
the user model and from the dishes model when we put
together that list of favorite dishes for our user.
The favorite dishes information that you store will not
actually contain either the user information or the dish's information.
Instead, it'll contain pointers to the documents for the dish document and for
the user document and then we will publish this information
when we are sending back this information in response to a get request.
Let's look at how we implement
this final assignment and also the various tasks in this final assignment.
To help you to understand what is required in
the final assignment or what you will be implementing in the final assignment,
let me demonstrate what your server is expected to do at the end of this assignment,
and then I will list out the three tasks that you need to perform in this assignment.
To get started, we need a set of dishes already on
the server side so that the user can mark some of them as their favorite dishes.
I have gone ahead and added in four dishes to my list of dishes on the server side.
You already know how to do this.
You have to log in as the admin and then post
this dish information to the server side one by one.
To enable you get the information for each of these dishes,
I have already provided you the db.json file which contains
the JSON documents corresponding to each of these dishes in the assignment resources.
You can open that, cut and paste information from there and then
create a list of dishes on your server side.
Here, you'll see that I have already performed the get operation on the
localhost:3000/dishes and then you
see that I have already obtained the list of dishes here.
What is important for us to note is that each dish will have its own dish ID here.
When you need to mark any dish as your favorite,
you need access to the dish ID for each of these dishes.
You can copy these four dish IDs and then save them so that when you
perform the operations to add these dishes to the list of dishes,
then you will be able to use this dish ID.
So I'm going to copy these four dish IDs and then save
them in a text document so that I can make use of them.
Before I can add dishes to my list of dishes,
I obviously need to log in as a user.
Let me go ahead and log in as one of the users.
To do that, let me do a post on the localhost:3000/users/login.
And in the body of the message,
let me type in one of the registered users.
I don't want to log in as an admin but as one of the other normal users.
So let me do this post to https://localhost:3443.
Now all these operations,
this is better to do it on the HTTPS endpoint rather than the HTTP endpoint.
We'll do a post to this endpoint and log in our service,
and in response, you should be able to get hold of the JSON web token.
So let's make a copy of this JSON web token because we will need this in order to
perform any of the operations to add dishes to our list of favorites.
Let me copy this token and save it in my text document.
Now, how do I add a dish to my list of favorites?
To do that, the first step is that we have
to access the /favorites endpoint.
If you want to add a specific dish to the list of favorites,
we just say /favorites and then add the dish ID into the URL here.
Let me paste in a dish ID which I want to add to my list of favorites.
Here, I have pasted in my dish ID to the list of favorites.
The body of this host message will
not contain anything because everything that I need is already in the URL.
And for the header,
I need to set up the authorization header,
and in the authorization header,
I need the token.
So let me copy the token here and then in the authorization header,
let's say bearer, and paste in the authorization header.
You can also do the same thing to obtain the token.
You can also do the log in through Facebook and then obtain the JSON web token.
I have illustrated to obtain the JSON web token using
the standard local authentication using the user name and password,
but it doesn't matter which way you obtained the JSON web token.
As long as you have the JSON web token,
you should be able to perform all these operations.
Let me perform the post operation on this endpoint and remember that this
is the dish ID for the specific dish that I want to add to my list of favourites.
When I post to the list of favorites,
you will see that my server will reply back with this document here in the reply body.
Now, let's examine this document to see what exactly it contains.
This document, as you can see, contains an ID,
but obviously because this is a JSON document,
in addition it contains a
Field here called user.
Now what does this user field store?
This user field is the object ID of the user
corresponding to whom this particular list of favorites is.
And look at the dishes.
The dishes is an array and it is an array of dish IDs.
And in this case, I just added the first dish to my list of favorites.
So, that's why I have just one dish in the array of dishes in my list of favorites.
So, this should immediately suggest to you how to design the schema for your favorites.
So, dishes contains the object IDs of each of the dishes,
and the user contains the object ID corresponding to the user.
You have already seen how I use
the information for doing population of the information when I do a get operation.
We have done that with comments already.
So, that should give you a big hint on how you would design the schema which contains
the user and the array of dishes in my list of dishes here.
Now, we have done the post on this.
Let's get the list of favorites.
So to get the list of favorites,
I need to perform a get operation.
Now, for the get operation,
I obviously need to also have the authorization information here because
you want a user to be able to retrieve only their list of favorites,
and no other user can retrieve the list of favorites for a different user.
So, this is very important.
So, this suggests to you that you need to
verify the user's authenticity even for the get operation.
Now, how does the post-operation
automatically get this object ID corresponding to the user?
Recall that when you include the authorization header here,
from the authorization header,
by the way you perform the authorization of the user,
direct that user properties already loaded onto the request object.
And so that is where you will get access to the user's object ID.
So, one more hint on how you will fill in this information.
So, that is why notice that when I performed the post,
I never specified the user because
the user's information should automatically be
derived from what we have supplied here in the authorization header.
So, one more hint on how you would go about implementing this.
So, that is why I said this assignment is a consolidation
of all the topics that you have explored in this course.
Now, I do not support a get operation on a specific dish ID.
It doesn't make sense for supporting that on the favorites,
in a specific dish ID.
Instead, we can perform a get operation on local host 3443/favorites.
And then we perform the get operation.
You would immediately notice that the document that is returned to you contains
the user's information already populated in by the get operation here.
So, the user's information.
So instead of the user ID there,
the user's information is already present in there.
This is done through Mongo's population.
So, that is another big hint on how you're supposed to implement the get operation.
Not only the user's information is filled in.
Now why would I want the user's information to be filled in?
Because that may be useful when I'm displaying information.
This may not be necessary,
but I'm just doing that just for the sake of completeness
because if you are retrieving the list of favorites for a particular user,
you automatically know who the user is,
and that particular user is logging in anyway.
But in case you want the user's information,
you can perform this operation to get hold of that user's information.
So, just to illustrate to you that Mongo's population can be used,
I have illustrated not only that in the list of dishes here,
the information about each dish is already populated into this array.
So, if you have a bunch of dishes,
the information of each of those dish should be populated into this array.
So, this is another Mongo's population usage
that you are seeing to fill in the dishes information.
Just by the way you set up the schema for your favorites,
this should be automatically possible for you by using
just the dot populate on the list of dishes here.
So, thats the second part.
Now that we're able to retrieve the get dishes method,
let me show you how you can perform a post operation where you can
add a bunch of dishes into your list of favorites.
Now, going back to this post,
if you need to add not just one but a set of dishes to your list of favorites,
now why would you want this?
Maybe on the client's side you might have a button which when
clicked will allow you to check mark a set of dishes from the list of dishes,
and then add them at one shot into your list of favorites.
So, to support that kind of an operation,
you may wish to allow a post to be performed on the slash favorites here.
Now, when the post is performed on the slash favorites, again,
you'll still need the authorization header.
But in the body of the message,
we're going to be storing the list of dishes as an array of this format.
So, this is a JSON document here,
so let me make sure that in my header,
the content type is already present there.
Now, this document will
contain an array of dishes like this.
So, each dish will be identified by
saying underscore ID colon,
and then here they will have the dish ID,
and so this would be nothing but an array of dishes.
So, let me add two dishes to my list of favorites here just to illustrate the point.
So, let me paste in the IDs from a couple of dishes into this.
So, when you perform a post on local host 3443/favorites,
this is how you compose the body of the post message here.
So, each dish that you want to add will be included in this format here.
Now, when you include them in this format,
and then post to that server side,
the server in return will send back the updated list of favorites for you.
So, when you receive the updated list of favorites from the server side,
you'll see that the user's information is already there,
but notice how the favorite dishes are stored in this array of dish object IDs.
So, the first one we had already added in the previous operation.
So the remaining two,
we just added to the list of our favorites.
So, those two object IDs are also added into
my dishes array in my favorites document here.
So, there you go. So, that is how you're supposed to perform
the favorites post on the endpoint like this.
Now, let's again perform a get operation on
the favorites just to see what the get operation features for us.
So when we perform the GET operation,
you will immediately notice that in the return favorites document,
you have the user's information there,
and then down below here,
the dishes is nothing but an array of Json documents here,
each one corresponding to a dish.
Now this is automatically taken care of by the mongoose
populate that we have done on the server side.
So all this information should be automatically populated on the server-side.
So that is how your post operations on the two endpoints work.
Now let me show you how you would perform a DELETE operation.
Now to delete a specific dish.
So let me perform a delete operation on a specific endpoint.
So we will go back to this endpoint,
and then let me just copy one of these,
and then I will delete one of the dishes.
So to perform the delete operation on one of the dishes,
of course as you see,
we don't need the body yet,
and we don't need the content here.
All that we need to do is to perform a delete operation on this endpoint.
So here you see that I'm doing localhost:3443/favorites/ and then the dish ID.
And then let me post this.
So when I delete a specific dish from my list of favorites,
you immediately notice that
my updated list of favorites is sent back to the client side by the server.
So you have the user here,
but note that in the dishes array I only have two dishes now.
The one that I have just deleted is gone from that list of dishes.
So if you perform a GET now,
your dishes array will continually to dishes in there.
Now, suppose I perform a DELETE on the favorites here.
So if I perform DELETE on the favorites endpoint itself directly,
then what it is going to do is to delete all my favorites and
also delete my favorites document completely from the server side.
So let me perform that delete operation on the server side,
and then it will return the fact that it has deleted this particular document,
so it just returns this document anyway.
But now if I perform a GET operation on my list of favorites,
I will retrieve a null there.
Meaning that I don't have this document on the server side.
So the favorites document is completely gone,
when I perform DELETE operation on local host column three from formerly slash favorites.
Now again, when I add a new dish to my list of favorites,
my favorites document will be set up all over again.
That's perfectly fine for us to operate with.
So with this demonstration I have shown you
all the various operations that you need to perform on your server side.
All the various operations on the various route endpoints
that you need to perform or implement on the server side.
Now that you have seen
all the various operations that the server side should support on the slash favorites,
and the slash favorites,
slash dish ID endpoints,
let me list out the three tasks that you need to complete in this assignment.
The first task of course is to implement the favorite schema and model.
This you will implement in the models folder in a file called favorite nodeJS.
There you will implement the favorite schema.
Remember that the favorite schema will store
the reference to the user's document object ID,
and an array of dishes document object IDs.
That's the big hint about how you are supposed to
design the schema and the model for your favorites.
The second task in your assignment is to implement the GET,
POST, and DELETE operations on the slash favorites endpoint.
GET will get you all the list of favorites,
populated automatically by Mongo's populate,
the POST should contain a list of dishes as specified
in the format that I have just demonstrated to you in the body of the POST message.
And so a bunch of dishes will be added into your list of favorites,
and DELETE operation on the slash favorites endpoint will
delete your favorites document completely from the server side.
Now if you perform a POST operation on slash favorite slash dish ID,
then the particular dish will be added into your list of favorites.
If your favorite document doesn't exist,
you obviously need to create that favorite document.
So that is also part of that POST operation.
So if at any point you find that the favorite document doesn't exist,
you need to first create the favorite document and
then add this dish into the favorite document.
So that is an important point also to note.
When you perform a POST on the slash favorites endpoint,
if the favorite document doesn't exist,
you need to create a favorite document and then add the dishes to your favorite document.
If it already exists,
then you only update that favorite document.
So this is one more hint on how you're supposed to implement the POST operations.
If you perform a DELETE operation on the slash favorites slash dish ID,
then that specific dish will be deleted from the list of favorites.
Now in performing the POST and the DELETE operations,
you should ensure that you won't add duplicates to the dish ID.
So before you add a dish object ID to the list of dishes,
always check to make sure if the dish ID already exists in the list of dishes.
Now this is where you can use the array indexOf method to check to see
if a document ID already exists in an array of documents.
So that's another big hint on how you are going to be implementing that part.
And the third task of course is to mount
the favorite router on the slash favorites endpoints by updating app.js file.
The favorite router itself will implemented in
the routes folder in favoriterouter.js file.
So with this I have described what you're
supposed to implement in the fourth and final assignment.
And I hope that this assignment will help you
to consolidate everything that you have learned in the course,
all the way from designing express router,
to doing MongoDB and also Mongo's schema and models,
and also performing the appropriate user authentication.
And as I have mentioned again,
only an authenticated user will get access to his or her list of favorites.
Even the GET operation can only be performed by
an authenticated user on the slash favorites endpoint.
And you would only fetch the favorites for that particular user.
You cannot allow a different user to access the favorites of another user.
So again, that also tells you how you're supposed to perform
the authentication on the different route endpoints.
With this I complete the description of the tasks in the fourth assignment.
Have fun completing this assignment.