‫In this lecture, we will allow the currently logged in
‫user to manipulate his user data.
‫And so now, by implementing user updates,
‫we're really leaving the domain of authentication
‫and are moving more into real user related stuff, okay?
‫And so instead of using the authentication controller now,
‫let's implement this updating functionality
‫right in their userController.
‫Okay,
‫so we have a bunch of handlers, so of routes,
‫that are not really implemented here, okay?
‫But let's leave them aside for now
‫and create our new handler function down here.
‫And this one is gonna be called updateMe.
‫And so again, it's updateMe because it's for updating
‫the currently authenticated user.
‫Later on, we will then also implement
‫this updateUser function here, but that is then
‫for like an administrator to update all of the user data,
‫while the user itself can only update, for now at least,
‫the name and the email address.
‫So, request, response, and next.
‫(keyboard clacking)
‫And we are actually doing this, so updating the user data,
‫in a different route than updating the user password,
‫well because usually in a typical web application
‫that's always how it's done.
‫So you have usually one place
‫where you can update your password
‫and then another place where you can update data
‫about the user or the account itself.
‫And so here, we're just basically following that pattern.
‫So again, let's start by laying out our steps.
‫And the first thing that we want to do here
‫is to basically create an error
‫if the user tries to update the password.
‫So create error if user
‫posts basically password data.
‫But then if not, we simply need to update the user document.
‫So simple enough, and let's of course start
‫with the first one.
‫Of course there will be a body
‫where we're gonna pass in the data,
‫and so if on that body there is data on password,
‫or a password confirm...
‫(keys clacking)
‫Confirm.
‫Well in that case, we want to return immediately
‫and create a new Apperror.
‫Oh and I guess we didn't yet implement it here,
‫or actually require,
‫so let's just grab it from here.
‫So AppError...
‫It's not here,
‫so the userController...
‫So AppError, here we go.
‫So 'This route is not for password updates.
‫'Please use /updateMYPassword.'
‫So basically the route that we specified before.
‫So updateMYPassword.
‫And then also, a code 400 for a bad request.
‫And let's actually try this one out right away.
‫And for that just two things,
‫first we need to send back a response,
‫so let's say res.status(200) for okay,
‫and then json,
‫add the status as success.
‫And later we will then also send the updated user,
‫but let's leave that for later.
‫So that's the response, and now we of course
‫also need to add this route to our user Router.
‫So that's of course similar to update my password,
‫so router, and of course a patch,
‫/updateMe,
‫then again, it is a protected route
‫so only the currently authenticated user can update
‫the data of the current user.
‫And so all of this is of course really secure,
‫again because the ID of the user that is gonna be updated
‫come from request.user,
‫which was set by this protect middleware here,
‫which in turn got the idea from the json web token,
‫and since no one can change the ID in that json web token
‫without knowing the secret, well we know
‫that the ID is then safe because of that.
‫And so because of this, everything here is safe.
‫So, userController.updateME.
‫Now okay...
‫So let's test this now.
‫Go ahead and copy this again.
‫And first of all, let's set the authorization.
‫Again from the Bearer Token
‫and of course with this environment variable.
‫Also it needs to be a patch request,
‫and we need to specify a body.
‫And I want to start by testing it,
‫causing this error of course,
‫and so let's specify a password,
‫and then a name.
‫So let's say that this is the name that we want to update,
‫so let's save this here.
‫And actually it is of course in the Users folder.
‫User Data.
‫And actually let's create a new folder here,
‫and put the stuff that is related to authentication
‫into its own folder.
‫So up here, we create a new folder
‫and call it Authentication.
‫That's not correct.
‫AH-THEN-TICATION.
‫(chuckles) So that's it.
‫And so the password is related to authentication,
‫also resetting the password, forgetting the password,
‫logging in, and signing out.
‫So, let's close these two,
‫and now log in as,
‫or actually let's create a new user.
‫So let's sign up here,
‫as a normal user so we can get rid of these two here.
‫And now I'm simply calling it, well, test again, all right?
‫And let's take a look at what users we currently have
‫in our database.
‫So we have hello and admin,
‫and so let's now use test.
‫And I'm always again, using the same password
‫to make it really easy.
‫All right, we need to give the name as well,
‫let's just call it J here.
‫And now indeed we get our token,
‫and we're already logged in,
‫and so now when we update the user,
‫that should be for this user that was just logged in.
‫So I'm not trying to update and of course,
‫no updating is yet implemented and so that's not gonna work.
‫All I want to see is the error that should happen
‫because I specified this password property here on the body.
‫So let's try it out.
‫And here we get this kind weird looking error,
‫but I guess it is simply because we didn't
‫actually update the route here,
‫so remember I just copied a route, so the URL,
‫and just pasted it here.
‫But of course, it needs to be updateME.
‫So let's try that again.
‫And so now we actually get that error that we specified.
‫"This route is not for password updates.
‫"Please use /updateMyPassowrd."
‫So great, that part is working,
‫and it's also working that we need to be authenticated.
‫Because let's say that we have no authentication,
‫and so let's say that: No Auth.
‫And so let's try that again now.
‫And so indeed, "You are not logged in!
‫"Please log in to get access."
‫So just to prove you that our authentication
‫is actually also doing its job here.
‫But of course, we want our Bearer Token,
‫and so now we get that other error.
‫Great, so let's now go ahead implement
‫the rest of the functionality for the updateMe handler.
‫So updating the user document,
‫and we could try to do it with user.safe.
‫So just like before, basically getting the user
‫then updating the properties, and then by the end,
‫saving the document.
‫But the problem with that is that there are some fields
‫that are required which we're not updating,
‫and then because of that,
‫we will some error.
‫And so just to quickly demonstrate to you,
‫let me actually do that.
‫Okay, so very quickly, getting the user here.
‫So findbyId, so request.user as we already know, .id.
‫And then let's say, user.name = 'Jonas'
‫and then await user.save.
‫But again you see that this will give us an error then.
‫But for now let's also of course declare it
‫as an async function.
‫And all right.
‫So let's test it now,
‫but we should expect to see an error now.
‫So let's of course get rid of this one,
‫and indeed we get: "Please confirm your password".
‫And so that's because passwordConfirm is a required field
‫but we did of course not specify it.
‫And so the safe method is not really the correct option
‫in this case.
‫So instead what we can do now is
‫to actually use findById and update.
‫So we could not use that before for all the reasons
‫that I explained to you multiple times by now.
‫But now since we're not dealing with passwords,
‫but only with this non-sensitive data like name or email,
‫we can now use findById and update.
‫So, let's get rid of this.
‫Let's also call it here updatedUser.
‫And then in here, we need to pass not only the ID,
‫but also the data that should be updated,
‫and then some options.
‫So the data, let's for now call it x here,
‫and I'm telling you why in a second,
‫and then the options that we want to pass in.
‫And so that's just like before,
‫the new option set to true,
‫so that it returns the new object,
‫so basically the updated object instead of the old one.
‫And the also runValidators set to true.
‫Because indeed we want the models to validate our document.
‫So for example, if we put in an invalid email address,
‫that should be catched by the Validator and return an error.
‫Now why am I putting x here, and not simply request.body?
‫Well that's because we actually do not want
‫to update everything that's in the body,
‫because let's say the user puts, in the body,
‫the role for example.
‫We could have body.role set to admin for example,
‫and so this would then allow any user
‫to change the role, for example, to administrator.
‫And of course that can not be allowed.
‫Or the user could also change their reset token,
‫or when that reset token expires,
‫and all of that should not be allowed of course.
‫So doing something like this would
‫of course be a huge mistake.
‫And so we need to make sure that the object
‫that we pass here,
‫so again that object that will contain the data
‫that's gonna be updated,
‫only contains name and email,
‫because for now these are the only fields
‫that we want to allow to update.
‫And so basically we want to filter the body
‫so that in the end, it only contains name and email
‫and nothing else.
‫So if then the user tries to change the role,
‫that will then be filtered out
‫so that it never finds its way to our database.
‫So what we want to do is to basically create a variable
‫and let's say filteredBody,
‫and then we're gonna create function in a second,
‫but let's just already use it here,
‫just so you see how it's gonna work.
‫And then in here we pass the data,
‫so the object that we want to filter,
‫so req.body, because that's where all the data is,
‫and then we pass a couple of arguments.
‫One for each of the fields that we want to keep
‫in the object.
‫So we want to keep the field called name,
‫and the field called email.
‫And again, a bit later we might then add more fields here,
‫for example later we might allow the user
‫to upload an image.
‫And of course that we then also need to update
‫in the database.
‫But for now, all we want to keep
‫in the body is name and email and filter out all the rest.
‫And so here, let's now use filteredBody,
‫instead of x of course.
‫And so now what we need to do is to actually implement
‫this function which will take care of filtering the object.
‫So let's do that here.
‫FilterObj,
‫which will take in an object
‫and then the rest parameters for all the allowed fields.
‫And so this will then basically create an array
‫containing all of the arguments that we passed in.
‫So basically that were passed in after this first one.
‫So in that case, it is an array containing name and email.
‫So what we need to do now is basically
‫to loop through the object and for each element check
‫if it's one of the allowed fields,
‫and if it is, simply add it to a new object,
‫that we're then gonna return in the end.
‫And probably there are more efficient of better ways
‫to implement this,
‫but let's just do it very quick here.
‫So we're gonna loop the object by saying
‫Object.keys of the object that we pass in.
‫So that's one of the easy ways to loop
‫through an object in JavaScript.
‫So, this here then basically returns an array
‫containing all the key names,
‫so the field names of this object,
‫and then we can loop through them.
‫Then our callback function.
‫And for each element, this is what we're gonna do.
‫So, if the allowed field array
‫includes the current element, so the current field name,
‫then we want to add that to a new object.
‫So let's quickly create that one here,
‫so const newObj
‫which is empty for now,
‫and in the end, that's the one that we're gonna return.
‫So newObj.
‫So if the current field is one of the allowed fields,
‫well then newObj with the field name of the current field,
‫should be equal to whatever is in the object
‫at the current element, so the current field name.
‫So don't if this looks a bit confusing,
‫this is again just standard JavaScript,
‫it has nothing to do with no JS or eXpress
‫or anything like that.
‫So again, all we do here is to basically loop
‫through all the fields that are in the object
‫and then for each field, we check
‫if it's one of the allowed fields.
‫And if it is, then we create a new field in the new object,
‫of course with the same name,
‫so still name element, with the exact same value
‫as it has in the original object.
‫And then in the end of course, we return that one.
‫And so this should now all be working here.
‫Then all we need to do in the end
‫is to send that updated user to the client.
‫So, user.
‫Now of course, we need to put the udatedUser then here,
‫give it a save again, and so now it should work.
‫Se really what we did here was..
‫update the user last, and before we did that,
‫we actually filtered out unwanted field names
‫that are not allowed to be updated.
‫So let's try that now.
‫And this user here is a regular user,
‫so we just created him,
‫remember with the name of J.
‫And so let's quickly take a look at Compass.
‫So it's a normal user, with a name of J.
‫And so let's now update then name,
‫and also try to update the role,
‫which again is not allowed.
‫But to see if our code is working, let's try it.
‫So there is the name already, and let's say
‫we're a malicious user
‫trying to change our role to admin.
‫So, everything is correct I guess,
‫so let's send this now,
‫and indeed here is our updated object.
‫So we get our new name, which is Jonas Schmedtmann,
‫and then the role, which is still user.
‫It didn't update the role to admin.
‫Perfect. That's exactly what we wanted.
‫So, give this a save and let's go back
‫and actually with this we just finished this video.
‫Next up, we will then implement a functionality
‫of deleting the current user.
‫So we worked on updating, next up we want to allow a user
‫to basically delete himself when he no longer wants
‫to be part of our application.