Now that the user and points are sitting behind authentication we're going to turn our attention towards
our tasks.
We haven't worked with tasks in a while and if we're going to set up authentication there's a few important
things we need to do.
First up we need to figure out how to create a relationship between a user and the tasks that they've
created.
This is going to be important to make sure that users can only access and manage their tasks and that
they can't mess with someone else's.
And that's exactly where we're going to start.
So to kick things off what we need is index data J S.
We don't need off dot J us anymore.
We're gonna need the User model.
We don't need the user router anymore.
We need the task model and last up we need the task router.
So we're going to kick this video off by working with these four files and the first file we're going
to touch on is a task that J S now there are two ways we could set up this relationship between a user
and a task.
The user could store something like the I.D. of all of the tasks they've created or the individual task
could store the idea of the user who created it and that second approach is the one we're going to go
with.
It is the better approach.
The only change we're gonna make to our data is we'll be adding a single field onto task it's going
to store the I.D. of the user who created it and that's going to allow us to lock down the task management
later on.
So right here let's go ahead and set up a another field on the task model we can call this.
Anything we like something like owner or creator or user or author would be appropriate you could use
any of those.
I'm going to go ahead and stick with owner for this one and we'll set it up like an object which we've
done for all of our other model fields.
Now from here we're going to customize the field we are going to set the type.
So let's go ahead and start with that the type for owner is gonna be an object I.D. and to set this
up we have to use something on Mongoose.
So right here as the value for type it is Mongoose dot capital S schema dot capital T types then dot
capital O object capital I d perfect.
So this is saying that the data stored and owner is going to be an object I.D. And that's correct.
Additionally we'll also set required equal to true for this like we've done for other fields that must
be provided and we're going to say that if you're creating a task you have to provide an owner for that
task no longer will it make sense to be able to anonymously create a task now that we have this in place
and we've changed our data.
What I want to take a quick moment to do is trash our existing database.
We have old task data inside of there without owners and that doesn't make sense to have anymore.
So what I'm going to do is right click the database and drop it completely.
Once the database is dropped we can go ahead on focus on actually creating tasks that belong to a specific
user.
And to do that we first need a user to create the task with over in post man.
We can get that done.
So we just deleted the database.
But as long as our app is running we can still add data to it.
It will automatically get created for us right here as an example.
We can fire off create user to create a new user.
And this is the user that we're going to use when creating our very first tasks that have the owner
field so to do this.
Let's head over to the task router and make a change to the very first endpoint we have inside of here.
This right here is the endpoint responsible for creating new tasks.
Now this end point doesn't provide an owner and it's not behind authentication.
We're gonna go ahead and change that.
The first thing we need to do is load in the off middleware so we can actually use it.
We'll start their contest off equals.
We'll be using require to load that in dot dot to get out of the routers folder forward slash middleware
forward slash off.
And once we have that in place we're gonna add it as the second argument to the post method.
So right here off moving the async callback function to the third argument position.
Now that authentication is set up it's time to make sure that when a task is created it's associated
with the person who is authenticated.
That means we're gonna be altering how we provide the data.
Right here I'm actually going to comment out this line and leave it in place so we can compare and contrast
the two solutions.
Now the new one is going to start off much the same way.
We can still create a constant called task and we still use the new operator with the task constructor
function though instead of just specifying request dot body we're going to provide our own object right
here.
We want all of the stuff from request dot body with the addition of an owner property.
So to do that I'll start by using the iOS 6 spread.
Operator with request dot body that's going to copy all of the properties from body over to this object.
So that would copy over the description for the task as well as optionally the completed value if it's
provided then right here we're going to hard code in the owner.
The owner is not something that should be specified via the request.
There is no need to pass the owner I.D. along with the data you send as part of the request body.
It's all from the authentication token right here owner is gonna have its value fetched from request
that user dot underscore I.D. the person that we just authenticated.
So with this in place when new tasks get created we're not just taking in the body data and saving that
we're adding on the owner property to actually create that association.
Now that we have this in place we can remove the old solution we can save the task router and we can
test things out to make sure that this endpoint is working as expected let's head over to postmen and
get that done.
So over here we already have a user created and since we created the authentication token was automatically
set up for us.
We're going to move over to the create task request.
Now there's no need to change anything here.
We're still passing in the necessary data and the you are L is fine but now that it's using authentication
it will be associated with a specific user the one who's authenticated.
I'm going to go ahead and fire off the create task request exactly as it existed before.
And down below we get a two a one we can see the stuff we had before with our task and also the new
field owner.
And right there we're getting the object I.D. of the user who was authenticated.
This is going to be the piece of data that links tasks to their owner.
And we're going to use that to make sure that someone can actually read a given task that they can update
a given task and that they can delete a given task.
If I'm trying to delete a task I need to be able to confirm on the server that I'm the one who created
it.
Now that we have the basics in place I want to mess around with some more advanced ways we can work
with this relationship.
So let's go ahead and do just that by heading over to index dot J S what we're gonna do is write just
a little bit of code down below to mess around with a couple of the features that we now have access
to.
And once we understand how these work we can integrate them into the task router to finish off those
other end points.
The first thing I'm going to do is load in the task model which we will be using.
So const task equals I will require it.
That is dot forward slash models of forward slash task.
And once we have that in place we'll set up a example asynchronous function for this little demonstration.
It's not something that will live in our app long term.
I can call it Main and we'll set it up as an async aero function just so we can take advantage of the
async await syntax and then down below we'll go ahead and just call it inside of here what we're going
to do is find our task by its I.D. the one that we just created.
Now I have the idea of the task right here so let's grab that.
Make sure you don't accidentally grab the owner I.D. We want the task I.D. not the user I.D. then from
Maine we're gonna go ahead and find it.
So right here const task equals I'll use a weight with methods we've used before task dot find by I.D.
and I will provide that I.D. as the first and only argument.
Now we should have access to the task and down below.
We're going to go ahead and print it right here console down log dumping task to the terminal.
Now to get this code to run all I have to do is save the file and down below what do we see.
We see our task showing up and I'm going to go ahead and print out the owner property specifically.
So right here that's going to be task dot owner when we do that like we saw before.
What do we get.
We get that object I.D. printing.
Now what if we wanted more than just the idea of the user.
What if I wanted the name of the user who created it to do that.
I would have to grab task dot owner and fire off another query down below to try to fetch that user.
And it would be a manual process where I search for a user by their I.D. and the value I use to search
is this one right here with mongoose.
There's a way to actually set up the relationship between our two bottles and it's gonna provide us
with some helper functions that will make this possible with very minimal code so to explore this what
we're going to do is continue to build off of the owner field over on the task model.
We're going to set up one additional property.
This right here is known as Wrath.
It allows us to create a ref which is short for reference from this field to another model.
And in that case it would be a reference to the following a user.
So right here inside of quotes I've typed out the model name exactly as we had typed it out in the file
below.
Over in the user model down near the bottom right here we typed capital you user as the model name.
That is the exact same one I'm using over inside of the tasks model to create that relationship.
Now that we have this in place we can easily fetch the entire user profile whenever we have access to
an individual task.
So over going to do is add a single line of code right here in between our two existing statements.
This one is going to take owner and convert it from being the idea of the owner to being the entire
profile of that owner.
Now we do that with the following.
It's asynchronous.
So we'll use a wait and it's available on task.
It's called populate populate.
Allows us to populate data from a relationship such as the data we have right here for owner we pass
to populate the thing we're trying to populate.
In this case we want to populate the owner.
We want to bring it from being just an I.D. to being the entire profile.
Next up to actually fire this off.
We use the following e x E C populate.
So what exactly is this line going to do.
It's going to go off and it's going to find the user who's associated with this task and task that owner
will now be their profile the entire document as opposed to just being the I.D..
So since the last time we ran the program we added two lines we added this line right here in the task
model and we added this line right here.
Let's go ahead and save the program and see what we get down below.
Instead of getting what we had before the I.D. I'm now getting an object.
This is the user document.
This is the user that created that task.
So now we have a relationship between tasks and users and we can actually use populate to figure out
which user created which task or which tasks a user owns.
So let's go ahead and reverse this direction.
We've taken a task and we found the user.
Let's go ahead and start with a user and find their tasks.
Now to do this I'm going to start by commenting out these three lines I'll leave them in place as a
reference but we're going to work on this second little project and we'll start by trying to find a
user by their I.D..
Now over inside of postman four that create task request.
We had the idea of the owner.
I'm going to grab that I.D. and bring that over to visual studio code.
And that's what I'll use to start with.
Now we will need access to the user model.
So right here I'll load that in concert capital you user and we'll use require it to load it in dot
forward slash models forward slash user next up down below we'll use find my I.D. with the user so const
user equals right here we're going to use a wait with user dot find by I.D. which we've used before.
We'll provide our I.D. and then we'll go ahead and print out the tasks property on user right here that's
gonna be console dot log user dot tasks.
Now this does not exist.
Users do not have tasks on that document and down below we see that is true because we're getting undefined
printing.
Just like we fixed that for tasks we're gonna go ahead and adjust that in the other direction for users.
Now what's this going to look like.
Well what we're not going to do is actually create a tasks array on the User model so up above for example
we do create a tokens array to store those tokens.
We're not going to do the same thing for tasks the tasks live in a separate collection.
Instead what we're going to do is set up what's known as a virtual property a virtual property is not
actual data stored in the database.
It's a relationship between two entities.
In this case between our user and our task to start off we'll be using something on user schema.
It is called the virtual and it allows us to set up one of these virtual actual Buttes.
Now it's virtual because we're not actually changing what we store for the user document it is just
a way for a mongoose to figure out how these two things are related.
Right here we pass to it two arguments.
The first is the name for our virtual field we could pick anything we wanted but something like tasks
seems appropriate.
You could use my tasks or users tasks and then we're going to set up an object.
And in here we're going to configure the individual field we're going to start by setting up ref like
we did for the task model and we're going to set this one equal to task.
So over inside of the task model we have a reference to the user on owner owner is a real field.
It is stored in the database.
Over here we have a reference between the user and the task on a virtual.
This is not stored in the database.
It is just for Mongoose to be able to figure out who owns what and how they're related.
Now we're going to set up two other fields on this virtual to get things to work correctly.
We have to specify the local field which will be a string.
And we also have to specify the foreign field the foreign field is also going to be a string so the
foreign field is the name of the field.
On the other thing in this case on the task that's going to create this relationship and we set that
up to be the owner of the local field is that is where that local data is stored.
So we have the owner object I.D. on the task and that is associated with the I.D. of the user here.
So the local field the users I.D. is a relationship between that and the task owner field which is also
a user I.D..
So now that we have this in place we can actually take that same code we had before use populate once
again and get all tasks that a user created.
So right here I'm going to save user dot and J asked the model file.
I'm gonna head over to index dot J S and we can see that right away we're already getting a slight change.
We went from undefined to no to actually get our real data.
We use populate.
So here I'm gonna use a wait I will be using populate on it.
User and I'm going to populate the tasks that virtual field.
Next up we're gonna go ahead and execute it by using E X E C populate.
Exactly like we did before to make sure things run.
And with this in place it's actually going to go off find all tasks created specifically by this user.
And it will store them in a real array on the user dot tasks property which means we'll get it printed.
Now once again nothing's getting changed about the user document.
It's not actually stored in the database.
It's a virtual right here.
I've run the program down below.
I get the one task that I find which is fantastic.
Now over inside of postmen we could create an additional task so up above I'll change the description
to something else.
Go to office something I'll be doing really shortly here after I'm done filming this video.
I'll go ahead and send that off and down below I can see it was created.
I can go ahead and rerun the script by just saving index dot J S and down below I can now see that two
tasks are showing up when I print that tasks array.
So there we go.
We now have a relationship between tasks and users.
And that's gonna be really important.
We're working with task data as we complete the rest of those end points.
Now the topic of virtual walls and populate is one of the more confusing Mongoose topics I don't expect
this to all be clear just yet.
That's why I wanted to do things in a little playground area before actually using them inside of the
task routes.
We'll get more experience with them soon and there'll also be challenges where you'll have to use this
stuff on your own.
I'm really excited to get to that.
So let's go ahead and jump in to the next one.