Welcome back in this lesson we're going to see some fun new material.
We're going to combine our user model the authentication that we've covered with campgrounds to make
sure that a user can't delete campground that he or she didn't create or a user can't edit a campground
that he or she didn't create.
And this is something called authorization.
So authentication and authorization there are different authentication refers to finding out if someone
is who they say they are.
Well authorization is once you know who someone is.
You figure out what they're allowed to do.
So think of it as permissions.
What can someone what what is someone authorized to do with their security clearance in our application
.
So if you don't own a campground if you don't have the same I.D. as the campgrounds author that you
won't be able to update or delete it.
So let's start simple and let's work with it so that you can't give you the edit form unless you own
the campground.
So let's go to our campground routes right here.
And what we want to do is if you try and go to the campground route or update and eventually delete
as well all three of them we need to have the same logic where we just check.
Does the current user's I.D. match the ID of the author for that campground.
So remember this is what our data structure looks like where we pull up the campground model.
We have author for each campground and there's an I.D. that's going to be an I.D. for a user it references
a particular user's object I.D. and then we have a user of course that has an object I.D. It's not specified
here but every user has an I.D. and we're going to compare the currently logged in users I.D. to the
campground author dot ID so we can do that pretty easily if we go up into our at it.
We'll start there.
And the first thing we want to do is check is someone who is user logged in at all.
And then if not we'll redirect summer.
If a user is logged in does user own the campground.
And if so we'll let the user run this code find my ID and delete everything.
Otherwise we'll also redirect.
So let's fill this in to start to see if someone's logged in.
We can just write if requested is authenticated.
We could also use the middle where we already defined here is logged in.
I'll show you in a moment why we're not going to do that.
The short answer is that we're defining our own middleware and just a little bit.
So we're going to combine that functionality instead of this middleware.
So if a request is authenticated if that is the case then we're good to go.
If that's not the case let's do a constant log to start.
You need to be logged in to do that and then we'll do a response.
And let's just do a send to start response out send and we'll send this actually.
So if we see that we'll know that we're not logged in and the first thing will be working.
So let's copy this code inside the if statement and indented properly.
OK.
So we have to be logged in.
Which is nothing new we've already written code to do this.
So you might be thinking where I'm going about this in a weird way which we kind of are.
But you'll see in just a moment why.
Let's test it out though.
Save start the server up.
And when I start up I'm not logged in.
No one is logged in.
So if I try and go to slash at it
it tells me you need to be logged in to do that.
So our first part is working just fine.
Then once we're locked down we're going to have another statement in here which is where it will check
.
Does the user own the campground.
And the way that we'll do that is pretty simple.
First thing we need to do is find the campground which we've already done right here.
And then once we find it we need to check if the ID of the author on that campground matches current
user which is request that user.
Then we're good to go.
So inside of here is where we actually do the does the user on the campground.
We'll keep the first bit to check if there's an error if there's no error then we'll check.
Does a user on the campground because that means found campground exists and then we'll have an if statement
and B if campground dot author ID as you might think that we could do this.
Equals equals equals.
Request that user dot underscore ID.
So let me just show you what I mean let's do a contact log campground author thought id and then below
it will do cancel that log request that user does underscore ID.
So a comment out the if statement.
So we'll see those two lines.
I will have to be logged in of course if I just try and refresh right now without being logged in we
have an error.
But if I do log in now has Potato Head
log in and then I go back to granite mine slash at it.
We have a problem.
Looks like let's see.
Well that was silly and trying to cancel like campground at Arthur campground doesn't exist.
It's found campground.
So I'll try it again restart the server.
First time we are fresh.
You know tell us you need to be logged in still.
So again we log in Potato Head.
Password.
OK.
Now if I try and get it
take a look at what we see here.
First thing that we print looks like this.
So that is found campground Arthur ID and then we have requests that user data I.D. and they look like
they're identical.
And when they're printed out they are identical.
But behind the scenes are actually not the same so requests that user id her underscore ID is a string
found campground author dot ID is an object it's a mongoose object.
And this is just a tricky one.
I forget about it from time to time it's really frustrating because they look the same when you're trying
to debug but the truth is the first one is not actually a string it's a mongoose object.
That one we printed out.
We see a string but that's just the two string version.
Behind the scenes it's not a string.
And this is a string.
So when we compare them it won't work.
So rather than comparing them with triple equals or double equals what we can do instead is use a method
that mongoose gives us for this purpose.
So what we do is write an IF statement put rather than checking campgrounds.
Author Dodd ID triple equals request at User ID.
We use dot equals.
There we go.
And now our IF statement should work except for the fact that this needs to be found campground again
what's coming back to the database that we're finding using that ID.
So we find that with the ID based off of the route then we check if the author ID on that particular
found campground equals the currently logged in users ID.
If that's the case we'll do one thing.
Otherwise we'll do something else.
So if that's the case we'll do this here render campground page of the edit campground page with found
campground.
Otherwise we'll do a rest does send.
You do not have permission to do that of course will change this eventually or it won't just be a red
dot cent but we'll have an actual message that displays.
So let's try to
go to our application go to a show page first thing if I try and edit it right now I need to be logged
in.
Now if I log in or I sign up as someone other than Potato Head so will do tomato head
and I try and edit that you'll see hopefully.
There we go I get you do not have permission to do that.
Now if we go back and log out and sign back in as Potato Head
and try it all again I try and edit.
I do have permission.
And I end up here.
So it's working.
Which is great.
Now what we'll do is actually refactor this into a separate function.
Most of this logic will call it something like.
Check user campground or ensure campground user something where we're basically checking does the currently
logged in user match this particular campground.
And the reason we'll move that into middleware is that we'll use it on edit.
We also want to use it on update.
We don't want someone to be able to send a request if they're not logged in.
So even though again just using the browser.
The only way to do actually visually get to the update to send data is using this form.
You could use postman you could send a request from postman and not be authenticated.
So we want the same logic here and we want to do the same thing for delete.
So we don't want you to be able to delete something a campground if you're not logged in.
And if you don't own it.
So what we'll do is write a middleware we'll copy this code for now.
I'll leave it there but we're going to go down for now just with our other middleware.
Well the final one called check campground ownership just like that.
And then we'll paste this code and we we'll have a little work to do here.
But the end goal is that on our edit we should be able to add our middleware here check campground ownership
.
We should be able to do it update.
And also on delete but we'll start with at it and what we want to do is check.
First you need to add in request response and next remember that so middleware is set up request response
next.
So if the user is currently logged in.
Keep moving if they you're not logged in rather than doing a rest us send.
For now we're going to do a restaurant redirect and we haven't seen this yet.
We can do redstart redirect back and that will take the user back to where they came from the most.
The previous page that they were on and very soon are going to show you how we can send a message.
Well the message we want to send is something like You're not logged in or you must be allowed to do
that but we're leaving it like that for now.
Then if they are logged in we're going to find the campground.
If there's an error we'll just redirect back as well.
Again this error would happen if the campground couldn't be found for some reason or if the database
is not connected or is some weird thing typically that we wouldn't actually see else if the campground
matches the requests user ID.
So if the user who's like in owns this then rather than rendering campgrounds edit because we don't
always want this middleware to render edit what we want it to do is move on to the rest of the code
in delete or move on to the code an update or an edit.
So that's where we do next.
Otherwise if they don't own it we'll do a rez redirect back.
Great.
So let's try this out save it and we'll go an update our edit route right here.
We can trim this down a lot so we don't need to do any of this really except for we do want to find
the campground and all that we'll do is if we find a campground we don't need to check if it matches
anymore because we're doing that in the middle where so all we want to do is find a campground can get
rid of all of this.
Almost all Office
format this correctly so will out a little bit.
There we go.
So because we added Scheck's campground ownership rate here all that we're doing now is if we get to
this point it means that we already checked campground ownership and that we made it through.
Otherwise if there's a problem we would have redirected that see with the error I'm getting is we have
a small syntax error here which is I somehow deleted my function declaration here and you can see it's
complaining that we're not handling the error which we could handle.
But the thing is if we get to this point there shouldn't be an error with finding PI ID because we did
it down here.
And if it works here then we should be good to go anyway.
So let's try it out though see if we have any issues.
Basically we just moved our code out into a separate function.
And remember a middleware is called Before we get to the right handler.
OK.
So let's give it a shot.
First thing let's go back and let's say try and click on edit.
I'm not logged in.
It should redirect me back to where I was