Node Auth Tutorial (JWT) #5 - Mongoose Validation
Summary
TLDRThis video script discusses enhancing user experience by creating custom error messages for a web application. It covers using Mongoose validation errors and custom error handling to provide users with specific feedback on form submission errors, such as invalid emails or passwords that don't meet criteria. The tutorial also introduces the use of a third-party package 'validator' for email validation and demonstrates how to handle errors in a centralized manner to return a JSON object containing relevant error messages. Additionally, it touches on the importance of hashing passwords using Mongoose hooks to ensure security.
Takeaways
- 🔒 The script discusses the importance of handling errors in web development to provide clear feedback to users when they submit incorrect data through a form.
- 📝 Custom error messages are created for different types of validation errors to improve user experience by informing them what needs to be corrected.
- 👤 Mongoose, a MongoDB object modeling tool, is used to define validation rules and custom error messages for user input fields such as email and password.
- 📭 A 'validate' property is added to the email field to ensure that the input is a valid email address using a third-party validation package called 'validator'.
- 🔍 The 'isEmail' function from the 'validator' package is used to validate the email address within the custom validation function in the Mongoose schema.
- 🔑 The script mentions the use of Mongoose hooks to hash passwords before storing them in the database, emphasizing the security best practice of not storing plain text passwords.
- 🔄 The process involves creating a function to handle and evaluate errors, which checks the error object to determine the type of validation error and constructs a useful response for the user.
- 📝 The 'handleErrors' function logs the error message and error code, which helps in identifying the type of validation error encountered during user input submission.
- 🔑 The script covers how to access and utilize the 'errors' object within the error message to extract specific validation error messages and paths for further processing.
- 🔄 The 'object.values' method is used to iterate over the errors and extract the necessary information to update an 'errors' object that will be sent back to the user.
- 📝 Lastly, the script discusses handling the 'duplicate key error', which occurs when a user tries to register with an email that already exists in the database, by providing a custom error message.
Q & A
What is the main issue with the current post request error handling in the script?
-The main issue is that the error handling provides a generic error message regardless of the specific error, which doesn't offer additional information to the user on what needs to be corrected.
Why is it important to create custom error messages for different types of errors in a web application?
-Custom error messages are important because they inform the user specifically what went wrong, allowing them to correct the issue more efficiently rather than guessing what the problem might be.
What is the purpose of using Mongoose validation in the script?
-Mongoose validation is used to enforce data integrity and to provide specific error messages when the data does not meet the defined conditions, such as required fields or minimum password length.
How does the script customize error messages for the 'required' field in Mongoose schema?
-The script customizes error messages by using an array where the first element is the validation condition (e.g., true for required) and the second element is the custom error message to be displayed if the condition fails.
What additional property is added to the email field in the Mongoose schema to ensure it contains a valid email address?
-The 'validate' property is added to the email field with a function that uses a third-party validation package to check if the input is a valid email address.
What package does the script use for validating email addresses, and how is it installed?
-The script uses the 'validator' package for email validation, which is installed using the command 'npm install validator'.
How does the script handle the error object caught during user creation in order to provide more useful feedback to the user?
-The script evaluates the error object to determine the type of error and then creates a JSON object with specific error messages for the email and password fields, which is then sent back to the user.
What is the significance of the 'handleErrors' function in the script?
-The 'handleErrors' function is significant as it processes the error object, extracts the relevant error messages, and returns a structured JSON object containing those messages, which can be used to inform the user of specific validation errors.
How does the script differentiate between different types of validation errors in the 'handleErrors' function?
-The script checks for the presence of 'user validation failed' in the error message and then iterates over the values of the 'errors' object within the error to extract and assign the appropriate error messages to the email and password properties.
What is the final step in the 'handleErrors' function after processing the errors?
-The final step is to return the 'errors' object containing the specific error messages for the email and password, which can then be sent back to the user as a JSON response.
How does the script handle the scenario where an email is not unique during user registration?
-The script checks for a specific error code ('11000') which indicates a duplicate key error. If this error code is present, it sets a custom error message indicating that the email is already registered.
Outlines
🛠️ Custom Error Handling in Web Forms
The script discusses the need for custom error messages in web forms when incorrect data is submitted via post requests. The current system provides a generic error message, which is not helpful for users. To address this, the video introduces the use of custom error handling combined with Mongoose validation errors. It guides through modifying the Mongoose user schema to include custom error messages for conditions such as required fields and minimum password length. Additionally, it explains the implementation of a 'validate' property for the email field to ensure a valid email address is entered, using a third-party validation package called 'validator'.
🔍 Evaluating and Handling Mongoose Errors
This paragraph delves into the process of evaluating Mongoose error objects to provide more useful feedback to the user. It points out that the current setup sends a generic error message regardless of the validation error encountered. The script suggests creating a separate function to handle these errors, 'handleErrors', which takes the caught error object and evaluates it to return a JSON object with specific error messages for the email and password fields. The function logs error messages and error codes to the console for debugging purposes and demonstrates how to send back a JSON response with error details to the user.
📝 Extracting and Utilizing Error Details
The script continues by explaining how to extract detailed error information from the Mongoose error object. It describes looking for the phrase 'user validation failed' within the error message to identify validation errors. The video shows how to create an 'errors' object to store and eventually send back specific error messages to the user. It details the process of using 'object.values' to retrieve the values of the errors and how to iterate over these values to update the 'errors' object with the appropriate messages based on the validation paths ('email' or 'password').
🔄 Cycle Through Errors for Custom Messages
This section demonstrates how to cycle through the array of error values and extract the necessary information to update the 'errors' object with the correct error messages. It explains destructuring the 'properties' from the error to access the message and path easily. The script then shows how to use the path to determine which property of the 'errors' object to update with the corresponding error message. The goal is to return the 'errors' object from the 'handleErrors' function to be sent back as a JSON response, providing clear and actionable feedback to the user.
🔒 Handling Unique Email Errors and Future Steps
The final paragraph addresses the specific error handling for non-unique email addresses, which is identified by a 'duplicate key error' code. The script explains that while custom messages can be set for other validation errors, the unique error requires checking the error code and manually setting the email error message to inform the user that the email is already registered. The video concludes by summarizing the error handling process and hints at the next steps, which involve hashing passwords using Mongoose hooks to ensure security by not storing plain text passwords in the database.
Mindmap
Keywords
💡Post Request
💡Custom Error Messages
💡Mongoose Validation Errors
💡Error Handling
💡Required Field
💡Minimum Length
💡Validator Package
💡Unique Constraint
💡JSON Object
💡Hashing Passwords
💡Mongoose Hooks
Highlights
The video discusses improving user experience by creating custom error messages for different types of validation errors in a web application.
Custom error handling is combined with Mongoose validation errors to provide specific feedback to users.
Mongoose schema is enhanced with custom error messages for required fields and minimum length conditions.
A 'validate' property is introduced to ensure the email field contains a valid email address.
The 'validator' npm package is used for third-party email validation.
A function 'handleErrors' is created to process and return useful error messages to the user.
Errors are evaluated to determine the type of validation failure and corresponding user feedback.
The process of extracting and utilizing error messages from Mongoose's error object is demonstrated.
A JSON object is constructed to send back custom error messages for email and password fields.
The importance of not using camelCase for the 'minLength' property in Mongoose validation is highlighted.
The video shows how to handle unique field errors by checking the error code for duplicate key errors.
A custom message is provided for the case when a user tries to register with an already existing email.
The video concludes with a preview of hashing passwords using Mongoose hooks in the next tutorial.
Storing plain text passwords is discouraged for security reasons, emphasizing the need for hashing.
The tutorial provides a comprehensive approach to improving form validation and user feedback in web development.
Custom error messages are shown to enhance user interaction by providing clear guidance on input corrections.
The use of Mongoose's built-in validation alongside custom error handling is demonstrated for robust form validation.
Transcripts
all right then gang so
we saw in the last video that currently
when we send incorrect data
with our post request we get back a
blanket error that looks something
like this no matter what the error is
whether that's an empty email property
or the password is too short etc
now that wouldn't be great to show a
user on a web page because it doesn't
offer
any additional info so they won't know
what to correct instead it would be good
to create custom error messages for
different types of errors
and we'll be using a combination of
custom error handling
and mongoose validation errors to do
this
so back in the code we can first come to
our mongoose user
over here and we can add some custom
error messages for the different
conditions that we specified like this
required so the way we do that
is by surrounding this inside an array
now the first
value of the array is the actual value
of this is it required well yes so this
is true
now we can pass in a second value into
the array
and that is a custom error message for
if this
fails so if they don't supply an email
then we can trigger an error message
which says
this thing right here so all i'm going
to say right here
is please enter an email
now i'm going to do the same thing for
requires down
on the password over here but this time
i'm going to change this to
password right now i also want to do the
same thing for min
length so let me surround this in square
brackets and again
the first position is going to be the
value of the min length and then the
second
position is going to be the error
message so i'm going to say minimum
password length is
six characters right so these are the
error messages
that we're going to basically throw if
these conditions
aren't matched when a user tries to
submit the form and we try to create the
user
right now we also need for the email
an extra property right here called
validate
now the reason i'm doing this is because
we want our email to be a valid email
address at the minute they could just
type in
any string like a name and there's
nothing here that says
otherwise so i could just type in mario
and
well it's a string it's there we've
typed something in
it's unique it's not in the database and
we've turned it to lowercase but there's
nothing saying
it has to be an email so we can add this
validate property to any different field
inside our schema
and this is going to be an array again
the first position in this
is going to be a function so i could
create a function
right here which does something in here
some custom validation
now inside this function we
automatically take in a value and that
value is the value of the user email
that is submitted to whatever the user
types
when we click submit so we take that
value and we can
validate it inside this function now
we'd return true
if we think it's valid and it passes we
return false if we think it's not valid
and in that case we would throw an error
with this error message the second
position
in the array so i could say please
enter a valid email so
inside this function you would want to
do something to validate that email
so to do this we could use a regular
expression for email and match it
against what a user submits
but also we could just use a third-party
validation package
which is what i'll do so this package is
called
validator and i'm going to install it
first of all so
we need to create a new console and i'm
going to say npm
install validator now
if you've got an old version of node and
npm then you need to pass in the save
flag
like so to save it to your dependencies
i've got a newer version so i don't need
to do that
and it's automatically going to register
it inside my dependencies
right here okay so now we have that
installed
the next thing to do is import something
from that package at the top over here
so this package has different functions
inside it that we can use to validate
different things
and one of those things is to validate
an email
so i want to import that function to
validate an email
from the validator package so i'm going
to say const
and d structure to get the is email
function so this is coming from the
validator package
we just installed so all we need to do
down here now
is instead of creating our own function
just passing
is email like so now this triggers a
function and it automatically passes
that value into it
that a user submits for the email and
then this
looks at that value and it returns true
if it is a valid email
false if it's not a valid email okay
so that's pretty much it for our custom
errors
right here we will come back to this one
later on because we're going to handle
that
slightly differently but for now this
will do
now before we go any further i have just
noticed an
error right here this min length
property should not be camelcase and
this l should not be a capital letter
make sure that is a lowercase otherwise
this won't work okay so now we have all
of these different validation messages
but at the moment
they are not really doing anything if we
were to send
a request with invalid data we would
still get back this blanket error
message
as we can see right here and that's
because in the auth controller we're
sending that right here so we're kind of
ignoring this error object that we catch
and that error object contains this kind
of
information on it so what we really want
to do
is evaluate this error object to see
what kind of error
is and then send back to the user
something more useful
like one of these messages or if there's
several errors
for example an error for the email and
an error for the password
send back both of those messages so
ultimately i'd like to send back an
object right here a json object instead
of just a string
and that json object will contain a
password property
and an email property now the password
property will hold the password error if
there is one
or a blank string or an empty string if
there's not an error
and the email property will contain the
email error if there is one
so all of this evaluating of this error
object right here
should probably be done in a separate
function so we're not bloating our code
right here
and duplicating code later on when we do
a similar thing down here
so let us now create a function at the
top of this file
to handle these errors so handle errors
and we'll create a const called handle
errors and that is going to take in the
error object that we catch
down in the try catch block right here
so what we can do now is just call that
function handle errors
and pass in the error object so up here
this is where we're going to evaluate
the error object and return
a more useful object which we can then
send back as json to the user
now to begin with all i'm going to do is
log to the console
the error message now the message
property comes on all of the errors that
we get
and it contains information about what
type of error this is
now i'm also going to log out something
else and that is the error code
now this code property doesn't exist on
most of the areas that we're going to
get
but it does exist on one specific error
that we're going to handle in the future
in particular that is the unique error
but we'll come to that later on
most of the time this will be undefined
but later we will
need it okay so let's just take a look
at this error message
when we send some invalid data so
let me first of all go over here and
press send and then
if we go back to the code we should see
down in the console if we open up the
other terminal
this thing right here so this is the
error message
and it contains user validation failed
and then it says please enter an email
and also please enter a password
this right here this is the error code
like i said undefined
for the most part okay so this
is if we don't enter an email and if we
don't enter a password but what if we
enter in something like mario which is
not a valid email
and also just one two three which isn't
at least six characters long
so this should still fail on two
accounts right because
inside the model it must be a valid
email and it must be at least
six characters long so let me send
this request and over here we can see
again
user validation failed so this is the
same in both
instances and this time it says please
enter a valid email
not please enter an email and it says
the minimum password length is six
characters
again the code is undefined so the
common thing here is
this string right here user validation
failed
so anytime there's any kind of error
which is dictated by
any one of these fields right here
required validate
required and min length then the error
message that we get is going to contain
this thing right here so we can look
for the presence of this in the error
message in order to handle these kind of
errors
in a particular way so let's do that
down here the first thing i'm actually
going to do is
create an errors object so errors is
equal to an object and inside here we'll
have an email property
which will be an empty string to begin
with and a password property which will
be an
empty string to begin with as well now
eventually
this is the thing that will be sent as
json back to the user
so if there's an email error we'll
update this property
if there's a password error we'll update
this property we're going to return that
at the end of this function so that down
here
we can store it in a constant by saying
const errors is equal
to whatever this function returns and
then we can
send that as a response right here as
json right
so this is what we need to populate now
dependent on the errors
so let's look for the presence of this
user validation failed
inside this error message first of all
so
first of all i'll do a little comment to
say validation errors
i like that and then i'm going to say if
and we're going to take a look at the
error
message and we're going to see if that
includes
a certain phrase and that phrase is
going to be this
thing right here so let me grab that
copy it and paste it in here
and now if this is the case then we can
do something
with that error now all i'm going to do
for now is
log that to the console console.log the
error just so that we can see it
so if i save this now and try to send
a request like this with invalid data so
send that
and both fields are invalid right let's
take a look at this object
now it is quite messy to see right here
in the console it's not
a great way of looking at them but
hopefully we will see this in a second
so this is the error object right here
so first of all we get the error message
at the top right this is the thing where
it says user validation failed
please enter an email please make sure
the minimum password length is six
characters etc
now down here we can actually see inside
the error object we have another
property called
errors so inside this object we have
the different errors that is created
by this request now there should be two
of them because this validation will
fail
and this will fail as well so inside
this error object or errors object
rather
there should be two properties one for
email and one for password
so if we scroll down a little bit we can
see right here the first one
email right so we can see there's a
validator error
please enter a valid email and down here
on this email object as well we see
other things we have a properties
property and we'll need that in a second
we also have
the path and the path basically says
what property
that we're failing on so the email in
this case uh the value which is what i
use entered etc
so that's the first object inside the
errors
object okay so the second one
is the password because we had an error
for the password as well and that's a
minimum length
error so again down here we have the
properties which we'll need in a second
we'll take a look at that in a minute
and we also have the kind of error well
it's a min length error
the path so what field failed and that
was the password one
and the value that a user tried to
create and that was one
two three right so ultimately remember
the end game here
is to populate this with an email error
and a password error if there are them
okay so
really what we want to do is access
inside
this error object right here the errors
property this thing right here this
errors property contains the errors it's
got two keys in it email
and password and both of those then
contain information about
those individual errors so
we need to take this errors property
right here
and we want to get the values of each
one of these things inside it we don't
necessarily need the key
we want the values of each key inside it
so how can we get those
well what we can do is we can use
object.values and then pass in this
errors object and that gets us the
values
of both of the different fields inside
it so this
value with the properties the kind the
path and also
this value from the password
so let me just do that first of all let
me log those to the console console.log
and we want the error overall object
then we want the errors
object inside that which is this thing
right here
and then we want the values of those
properties
so the way we do that is by saying
object dot values and then surrounding
this
okay so it takes this object right here
this errors object and it gets us the
values
of the different things inside that
object so not
the keys but the values so if i log that
to the console now if i save it
and just quickly this must be a capital
o otherwise this won't work so save that
again
and now let's try sending a request
and if we go back we should be able to
see
these different values so we can see we
have
these different objects right here so
let me just show you we have this
array and the first one the first object
is right here with the different
properties and other information
and remember these properties are
ultimately what we want to get because
they contain the message that we write
and also the path to say what property
we need to update
and the second one down here is for the
password
so we have again the properties with the
message inside it
and the path etc okay so we want those
ultimately but now we have an array
of the values so what we could do is we
could actually
cycle through that array of values
right here and then for each one of them
extract the information that we need
and update these different properties so
let me now say
for each on these so we can do that
remember because this is an array
and for each one we'll take in the
individual
error and inside here i'm going to just
console.log
the error and i'm going to log the
properties property
on each one of them all right so error
dot properties
like so so let me save that again and
come and try to send a request
that's not valid again and if we come
back over here
now if we scroll down we should have two
objects right here
we have this one and we have this one so
this is ultimately
what we need so for each one of these
now we can say okay well the path is
email so this is
an email error so i'll take this
property right here
and we're going to update that and i'll
set the message or the value of that
property
to be this thing right here and i can do
the same
for this one as well i'll say well okay
this time the path is password so i'll
update the password property
and i'm going to set the value of that
equal to this thing okay
so what i could do is instead of
passing in the error right here i could
destructure
and get the properties
from the error like that and to do that
i need to place this in parentheses
so now all we're doing is destructuring
the properties property
from the error and now we have access to
that without saying error.properties
this does exactly the same thing and i
can demo that
by sending a request again
and over here we get the two same values
so these are the properties objects
right
okay so we have those now what is the
next step
well all i want to do now is access the
errors that i have
right here or the error object rather
and
then i need to decide which property i
want to update
well to do that i can pass in a string
inside
square brackets so for example i could
say email right here
and set that equal to some value and
that would
take this property right here the email
based on this
and it would update it with this value
now instead of passing through email i
can get
that from the properties path property
right here
so i'm going to say properties
dot path so that's either going to be
email or
password right so it's going to take
whatever property that is and
update it with something now i want to
update it with
the message so i can say properties
dot message like so and that's all there
is to it
now we're updating this error object
right here and in fact
i'm going to call this errors instead of
error makes more sense because there
could be more than one
so update it here and here so we're
updating those with
the different messages we have and if
there's only one of these
then we're just going to cycle through
the one of them and update that
particular property the other one
will remain blank meaning there's no
error all right
now at the end of all of this we want to
return the errors
object that we have right here so let's
do that
so i'm going to save this now and if we
scroll down
then we're getting those errors right
here because we're returning them from
this function
and now we can send back some json
instead of just some text so
dot json and inside we want to send back
some json
and that is basically going to be the
errors that we have
okay so that's all there is to it we're
sending now this thing
up here back to the user in json format
after we've populated the different
values so let's try this
and come over here so we need to send a
new request now and hopefully we should
see an error for this and an error for
this
so send and we see please enter a valid
and minimum password length is six
characters so
let's do an email so at google.com
and press send and that value goes away
that error but we still have this one
so let's do test123 instead
and press send and hopefully
yep this works and we get the user back
that mongodb creates
for us okay so there's one more error
that we need to handle
and that is to do with whether an email
is unique
so if i try to do this again and click
send
then i'm going to get some errors right
here but
this time we don't have any information
here so we don't really know what the
error is
now the error is that this has to be
unique remember we specified that inside
the user controller over here where we
said unique is true
now unfortunately we can't do a custom
message over here for an error like the
other ones
over here we can't do that with unique
instead what we have to do
is look for information about this error
over here and that information is the
error code
so notice when i sent this request over
here we get this error code right here
and it says
duplicate key error so basically this is
saying that
this email that you're trying to sign up
with should be unique
and this email already exists in the
database and if we take a look inside
the database
if i scoot this down and go to mongodb
i'm going to refresh over here
we should now see mario at google.com
as a user so it won't create that again
and that's a good thing but we do need
to update the error
for this so we can look for this code
and we can
react to that and send back a custom
error based on that
so let's do that now i'm going to say
duplicate
error code and underneath this i'm going
to say if
error.code is triple equal to 1 1
0 0 0 so that's this thing over here
then we're going to do something so the
thing we want to do
is update this property so i'll say
errors
dot email is equal to some kind of
string and i'll say that
email is already registered all right
so at this point we can just return
the errors like so there's no need to go
any further and check these errors as
well because we already have this
whopping error
and we can tell that to the user so
we're returning errors here
if this is the case otherwise we return
them at the bottom after we've done all
of this jazz
are right here so let's save this and
see if this works
so if i go back over to oops i need
postman
so if i try to request this again send
it should say that email is already
registered
all right then cool so now we've sorted
all of our errors out by using this
error handler function
at the top right here now this bit right
here i know
was a little kind of long-winded and a
little bit complex but it's just a way
to create custom messages there are
other ways to handle errors as well
and you might have your own preferred
way this is just one way by cycling
through the values of the errors
finding the message for each one and
updating an errors object
with that message right here so we have
all of these errors
sorted out now eventually we will show
all of the errors on the web form
after a user submits it whether that be
the login form or the signup form
and we will create those forms
eventually but next up before we create
the forms
i want to show you first of all how to
hash passwords
and for that we're going to be using
mongoose hooks because
we never really want to store
plain text passwords over here in the
database that is a
bad bad idea in case your database is
compromised
and all of your passwords are then on
show so we'll be hashing those passwords
first of all
and we'll see how to do that or how to
start that process at least
in the next video using mongoose hooks
5.0 / 5 (0 votes)