‫Welcome back.
‫So, we have implemented authentication
‫in our project up until this point.
‫And, it works just fine.
‫However, sometimes, simply authenticating,
‫so, logging a user in,
‫is really not enough.
‫And, so in this video,
‫we're gonna implement authorization as well.
‫So, imagine the act of deleting a tour
‫from our database.
‫So, not every user should, of course,
‫be allowed to do that.
‫Even if the user is logged in, right?
‫So, we basically need to authorize
‫only certain types of users,
‫to perform certain actions.
‫And so that's exactly what authorization is.
‫It's verifying if a certain user has the rights
‫to interact with a certain resource.
‫So, again, with authorization we basically check
‫if a certain user is allowed to access a certain resource,
‫even if he is logged in.
‫So not all logged in users will be able to perform
‫the same actions in our API, all right?
‫And this is a very common scenario that should
‫be implemented in each and every
‫web application usually, all right?
‫So we're gonna build another middleware function here,
‫this time to restrict certain routes.
‫For example, for deleting tours.
‫So, this means that we're gonna build another
‫middleware function here.
‫This time, to restrict certain routes,
‫like, for example, deleting tours,
‫only to certain user roles.
‫Okay?
‫And so let me actually show you how that would look like
‫in practice.
‫So here, in the tour routes,
‫let's go back to that example of deleting tours,
‫and so let's add some middleware into the stack here.
‫So authController, protect.
‫So first, we always need to check
‫if a user is actually logged in, okay?
‫So if an administrator is trying to delete a tour,
‫they would still need to check
‫if he's actually logged in, right?
‫So the first middleware in the stack here,
‫will always be the protect one.
‫But then, after that one, we will also have the
‫authController.restrict.
‫So restrictTo, okay?
‫And into this function we will then pass some user roles,
‫which will be authorized to interact with this resource.
‫In this case, with deleting a tour, okay?
‫So let's set this one to admin.
‫So, only to administrators.
‫Okay, and so now we are dealing with user roles here.
‫So just like admin.
‫And right now, we don't have that in our user model.
‫And so let's quickly implement that here.
‫All right.
‫So, let's do that.
‫Actually, before the password stuff, so like here.
‫And down here you can actually see how our uncaught
‫exception handler is working just fine,
‫because restrictTo is not yet a function, right?
‫We didn't implement it yet.
‫I simply used it in order to show
‫what exactly we're gonna build.
‫And so of course there's an error,
‫and so nodemon is now waiting
‫for us to restart the server, okay?
‫Anyway, the role here should be of the type String,
‫and now I'm gonna use the enum validator in order to only
‫allow certain types of roles here to be specified.
‫And these are the general, so the normal users,
‫so let's just call them user.
‫Then, we have the tour guide,
‫we have the lead tour guide,
‫and we have the administrator.
‫So, I'm just calling that admin, all right?
‫And these user roles that we have here will of course
‫be specific to the application's domain.
‫So, for example, when you're running a community site,
‫it's not gonna make much sense to
‫have a guide and a lead guide.
‫Instead you will probably have, like, moderators
‫or contributors, or members.
‫So, you will always have different names,
‫depending on the type of application that you're writing.
‫But in our case, this is what makes sense.
‫Then, we also want to set a default here,
‫so we actually don't have to specify always
‫which type of user we're creating.
‫And so user, the normal user, let's say,
‫is the one that's gonna be created by default.
‫So let's now actually go ahead
‫and delete the users that we already have,
‫because they don't have any roles,
‫and so we don't need them like this anymore.
‫All right.
‫And so let's actually also go
‫ahead and create some new ones.
‫So, I'm gonna sign up here as
‫as hello@jonas, and so that's now gonna be a normal user,
‫and now we could not get any response,
‫and that's of course because we have this error here,
‫and so, let's very quickly take out this line of code.
‫And now the error is gone.
‫And so now it should run,
‫and indeed we now have this user,
‫with the role of user, okay?
‫So that's our default,
‫but now let's create an admin here.
‫And to make that really clear,
‫let's put it here in the email as well,
‫and now we need to really specify the role,
‫and set that one to admin.
‫Send that, and so now we got here our system administrator.
‫Cool.
‫So, let's go back here, actually put this code back on,
‫and we will now make it so that we can actually pass
‫multiple arguments into this restrictTo.
‫So, I want the admin to be able to delete tours,
‫but also delete a guide.
‫All right?
‫And so let's add that here as well.
‫Okay?
‫So the admin and the lead guide can now delete tours,
‫but not the normal guides, and also not the normal users.
‫All right?
‫So this is how restrictTo is gonna work,
‫let's now go ahead and implement it.
‫So exports.restrictTo,
‫and now, how are we actually going to implement this?
‫Because usually, we cannot pass arguments
‫into a middleware function, right?
‫But in this case, we really want to.
‫We want to pass in the roles,
‫who are allowed to access the resource, right?
‫So this case, the admin and the lead guide.
‫So we need a way of basically passing in arguments
‫into the middleware function in a way
‫that usually does not work.
‫So, how are we going to do that?
‫Well, in here, we will actually create like a
‫wrapper function, which will then return the
‫middleware function that we actually want to create, okay?
‫So, this is the restrictTo function,
‫and in here we want to pass an
‫arbitrary number of arguments.
‫So, basically, of roles.
‫And so we can use the rest parameter syntax,
‫which is again new in ES6,
‫and this will then create an array
‫of all the arguments that were specified, okay?
‫So we're creating this function,
‫and right away we will then return a new function.
‫And this is the middleware function itself.
‫So, request, response, and next.
‫Okay?
‫Make sense?
‫And so this function here will then basically
‫get access to this role's parameter here,
‫because there is a closure, okay?
‫So, just as a comment here to explain,
‫roles is an array.
‫So, for example, it might be, in this case,
‫admin, and lead guide, okay?
‫So when will we give a user access to a certain route?
‫Well, basically, when its user role is
‫inside of this roles array that we passed in right?
‫So let's say we have the normal user now,
‫which has a role of simply user,
‫so let's write it here.
‫Role is now just user.
‫And so basically it's not contained in this array,
‫and so therefore, that user does not have permission, okay?
‫And so, let's write that in code.
‫It's actually quite simple.
‫So, if not roles.includes, and okay,
‫once more includes is a very nice array method
‫that is in Java Script available on all arrays, okay?
‫So, if this roles array does not include
‫the role of the current user,
‫then we do not give permission to that user.
‫And where is the role of the current user stored?
‫Well, let's remember the line of code
‫that we actually put up here,
‫right in the end where we grant access
‫to the protected route,
‫we store the current user in request.user.
‫And remember how this protect middleware
‫always runs before restrictTo, right?
‫So, here, we first have protect,
‫and then we have restrictTo.
‫And so by the time this middleware function here runs,
‫this one has already completed,
‫and has put the current user on the request object.
‫And so now, we can use that here.
‫So request.user.role.
‫So that's where the role is stored.
‫So, simple.
‫In this case, we create a new error.
‫So just like before, and now we say
‫you do not have permission to perform this action.
‫And now a new status code, which is 403.
‫And this one means forbidden, okay?
‫So there really is a specific
‫http status code just for this case,
‫so for authorization basically, all right?
‫And, well, otherwise, we simply call next.
‫And that's really it.
‫So that's as simple as it is.
‫So let's quickly recap what we just did here.
‫So, in here, we first run the protect middleware.
‫Then, restrictTo middleware,
‫and only if these two middlewares pass to the next one,
‫we go to the lead tour.
‫And so basically this route handler,
‫or this route controller, is protected,
‫and is also restricted by this
‫middleware that we just created.
‫Then into this function,
‫we pass all of the roles that are
‫allowed to interact with this resource.
‫So, basically, which are allowed to run
‫this handler function, okay?
‫And so, this restrictTo function will then run,
‫and return the middleware function itself, okay?
‫And that middleware function itself is actually this one.
‫It will then, because of the closure,
‫have access to roles, okay?
‫And so, let's say that the role of the current user,
‫which is, remember, stored in req.user.role, right?
‫So, let's say that his role is user,
‫and since that role is not in this role's array,
‫well, we then get this error, okay?
‫And so that's what this roles.includes tests here for, okay?
‫But of course, if it is included,
‫then we pass to the next middleware.
‫Which again, is then the route handler itself.
‫Cool.
‫So, I hope that makes sense.
‫Let's now go ahead and quickly test it.
‫Okay?
‫So right now, we have this token here,
‫stored into the JTW variable, right?
‫So remember that from the last lecture.
‫So, we are in this dev environment,
‫and so here is that variable.
‫So exactly the one that is down here.
‫All right?
‫So if we were now to delete a tour,
‫we would then have to specify that variable in there, right?
‫So let's go to authorization,
‫the bearer token,
‫and then it actually already puts it here for us.
‫So it already knows that this is the
‫one that we want to use, because, well,
‫we used it before, okay?
‫Now, I want to start by showing you that
‫a regular user cannot delete a tour now, okay?
‫And so let's start by logging in as a regular user.
‫And so that's hello, right?
‫Remember, right now we have hello@jonas.io,
‫which is a normal user, and we have admin@jonas.io.
‫And we still have this old one here, let's get rid of it.
‫All right.
‫And so I'm gonna start with hello@jonas.io.
‫Okay?
‫So, logging in, then that token is gonna be stored
‫into the environment variable,
‫and now we are ready to delete a tour.
‫We actually also need to get an ID now,
‫so let's quickly get one from here,
‫so we're basically gonna delete one of our tours here.
‫So let's just use the last one here.
‫So, the stargazer.
‫Okay?
‫And let's see if we get our error message.
‫And, indeed, you do not have permission
‫to perform this action.
‫So, 403.
‫So, indeed, it's kind of working, right?
‫But, to make this complete now,
‫let's of course login as the admin.
‫So, admin.
‫Login.
‫And so this token is now stored into this variable.
‫And so if you run this now,
‫we should be able to effectively delete the tour.
‫Wanna see?
‫And, it's gone.
‫So we have a code of 204, no content,
‫which is the standard when deleting,
‫but now if we get all our tours,
‫we should now see a number eight here,
‫so only eight results,
‫and that means that the last one is now gone, okay?
‫And so right now, as we just proved,
‫an administrator has the permission
‫to effectively delete tours, okay?
‫And, I really cannot stress enough
‫how important this piece of code here is.
‫So basically, where we get the role from the current user
‫from the middleware before, okay?
‫So, storing the user onto the request as we did here,
‫is really crucial in order for
‫this next step to actually work, okay?
‫So, the ID that is encoded into the Jason web token
‫is what makes our code then know whether
‫the user that's trying to perform the action is a user,
‫or if it's an admin, or if it's a lead guide, or whatever.
‫Again, because that data is coming
‫from this protect middleware.
‫Great.
‫This was yet another important piece of the puzzle
‫in implementing our authentication workflow here.
‫And of course, you want to restrict a lot of other routes,
‫for example, like updating here, okay?
‫But I'm gonna leave that for a
‫later point of the course, okay?
‫Right here, I just wanted to show you
‫how all of this works, okay?
‫So, I think I did that successfully.
‫I hope you understood how this worked,
‫and of course, if not, you can always ask a question
‫in the official Q and A section.
‫Anyway, there's some more great content coming up right now
‫and so, let's move on.