Press "Enter" to skip to content

MERN Stack & GraphQL – #6 Resolvers and Models


right so once we have a definition for a
model for a user model let’s go back to
our user resolver let’s go ahead and
implement some of these methods over
here there’s quite a few things we will
have to do inside of these resolvers if
you want to query the users well we have
to make sure that you’re actually
authenticated so I’m gonna believe a
bunch of to do is so the first thing we
check is if the user is actually
authenticated or not the second thing
we’re gonna work on it would be the
projection now projection is a concept
in MongoDB and it basically refers to a
technique of selecting specific fields
from your database or from your
collection now for example if you want
to select users we might have a query on
users in graphical of course and for
example we want to select the name of
those users now it doesn’t make sense to
query the entire user object in the
database because we’re only asking the
server for a name so using projection
we’re gonna be able to efficiently
select the exact fields that the client
is asking for and also optimize the
queries that we’re making to our
database so we’re gonna work on that in
the future for now I’m just gonna leave
a to-do note so for the time being we
can actually do a return statement of
user dot find we can pass in an empty
object and this way we’re basically
going to select everything from the
database once again I’ll leave another
to do we’re gonna need to work in
pagination here because we don’t have
any records yet and because we’re not
gonna have that many of them for now
because we’re just developing it’s fine
to do this but of course in the future
we’re gonna optimize this to do a proper
pagination on the database because we
don’t want to return the entire set of
users from the database now this user
object is being highlighted for us
that’s because we need to import it so
let’s do an import of user and we could
have a name import because we could
immediately define an index.js file on
the models and we’re gonna import it
from models so we need to go one level
up like this so let’s actually go back
to the terminal I’m gonna try to do a
yarn dev let’s go back to the app and
fire a query and this will get an empty
set of users and that’s because we don’t
have any users in the database yet let’s
implement another resolver so this one
is going to request and
individual user by ID and the first
thing we need to do is we need to
actually check if the arguments idea is
actually a valid object ID and for this
we can actually do an import of Mongoose
from Mongoose so we can have a check
over here
if Mongoose the types dot object ID is
valid this is a utility method that we
can actually call in this case we need
to negate it so for instance if the
object ID from arguments dot ID is not
valid in fact we can actually just pass
in the ID and destructor it from the
ergs so we’ll check if the ID is valid
if not we’ll go ahead and throw an
exception now in this case you can throw
in a generic error but there’s a bunch
of customized errors that we can
actually use with a polo out of the box
so we go ahead and look for a polo docs
we can go ahead and switch to the air
handling section this one is gonna tell
us about some of the common errors that
you might encounter so for example
authentication error and this is when
you’re not authenticated and you’re
trying to access a protected route or
service or a resource you might also
have a forbidden error in this case for
example you’re logged in but you’re not
allowed to access a resource and we also
have a user input error as well as a
generic Apollo error in this case I’ll
be using a user input error so let me go
back in here I have an import of that
exact object from Apollo server express
so we can actually go ahead and throw a
new user input error and we can
basically say let’s inject the ID inside
the string and there might actually be
security considerations about this now
we’re going to talk about security
afterwards but for now we’re basically
going to return that same ID the way
that they provided us with and it will
pass in a description so we’d say that
whatever the user provided is not a
valid user ID like this so I’m just
gonna leave off a comment sanitization
we’re gonna come back to this resolver
and a bunch of other ones in the future
and we’re gonna fix up some of these
security or performance issues like I
said in the future but this should be
fine for now so once we confirm that the
argue
is correct and once we confirm that this
is actually a valid user ID we can
actually go ahead and return user dot
find by ID we can pass in the ID inside
of course in here once again we need to
do auth we need to do projection because
we need to check for the exact field
that the client is asking for so for
instance they’re asking for a subset of
the actual user model and of course last
stop the assign it ization part belongs
in here of course it’s useful to query
users from an API but it’s also very
useful to actually create them in the
first place now of course in the signup
mutation we need to check if the user is
not authenticated so leave off a comment
not off next up we need to do a bunch of
validation on the arguments and this is
the part that we’re gonna get into in
the validation video we’re gonna talk
about that in more detail but the last
step would be to actually create the
user itself and for this we can
basically call user dot create and we
can pass any arguments inside now once
again these arcs come from the resolver
it seems like a cold em argue in fact
this is actually arcs with an S you can
call them anything but the idea is that
this object contains all of the
parameters passed from the client so in
this case we could basically just call
user create once again this user create
just like user ID by ID or user find an
empty object or whatever you pass in all
these three calls are asynchronous but
because a polar works with promises but
can actually just go ahead and return
the result of that call to our resolver
once that call is resolved so once that
promise is resolved we’re gonna get a
result from the server so a pole is
gonna handle promise resolution and
promise rejection on its own so go ahead
and do a mutation let’s do a signup
mutation we need to make sure that we
pass in the set of required arguments
and this is what I was talking about
with regards to basic validation in
graph QL that’s because we already have
a user type and we already defined some
fairly primitive but still pretty useful
validation on the arguments like I said
the arguments have to comply with the
types that we’ve defined in our schema
so
for instance the email has to be a
string and the email also has to be
provided so it can be a null and the
same applies for other arguments as well
so we can go ahead and back in our
browser let’s pass in an email I’m gonna
do Alex at gmail.com and a pass in a
username
let’s do Alex 12
let’s also pass in a name this one of
course would be Alex and last stop
password we can pass in a password let’s
do secret like this and let’s see now we
have to close this off the pair of curly
braces we can request an ID and name
email what else username create it out
perhaps and this should basically be it
for the schema so let’s try running it
and once we do we get back an object so
it seems like it’s been created in the
database successfully so back in M lab
I’ll go back to our collections I’m
going to refresh the page and we should
see a user’s collection and in fact we
are also gonna be able to see the user
inside that collection as well so we can
actually expand this one and we could
see that all of the fields have been
initialized so for instance we get the
email the user name the name as well as
the password if you’re paying attention
you’re actually gonna see that the
password is stored as plain text and
this of course needs to be fixed so in
fact we need to do is we need to store a
hashed password instead of the plain
text password so in order to do that we
are gonna pull in another library so if
I go back to NPM J’s org and if we look
for decrypt there’s actually two
variants of the same library there’s one
called bcrypt
but it’s more of a low-level library and
it does have quite a few dependencies
they need to install but there’s one
that is pure JavaScript and has the
exact same API but it doesn’t have the
environment limitations or quirks as the
previous one so we can actually go ahead
and install it as a dependency let’s do
you’re an ADD bcrypt j/s we can go back
to a resolver and of course in here what
we could do is after the validation has
been passed we can actually go ahead and
create a password variable for example
we can grab the arguments password and
then of course we can call decrypt hash
function on it
but something like this could actually
be outsourced on the model itself so
what we can do is we can actually create
a method on the model so going back to
our user model back on the schema but
can actually create a hook so let’s go
ahead and reference the schema and there
is a hook that’s called pre save and
this one is gonna be called before the
model is saved now in this case we’re
actually calling create method on the
user model the create method is actually
going to assign all the properties from
the arguments object and it’s going to
eventually call the save method now this
save method can actually be intercepted
inside this hook over here and actually
if you want to learn more about it you
could go back to Mongoose but switch
back to the documentation and if you
click on read Doc’s and you can switch
to a middleware section and if you look
for pre let’s look for a pre save and
there you go you can see that you have
your schema you define your schema with
Mongoose and then you call schema pre
save and this one like I said is gonna
intercept all save calls on your model
so what we need to do is we need to pass
any callback let’s actually copy it and
we’re gonna paste it in as the second
argument this one is gonna accept a
callback called next we’re gonna need to
call it after we do all of our
operations which happens to be
asynchronous in this case because we’re
gonna be hashing the password but in
this case we first of all have to do a
check so we can check if this is
modified on the password field so if the
password field has been modified then in
this case we do need to know that the
password needs to be hashed but if it’s
not the case then we can simply call and
next ourselves so let’s in fact import
hash from bcrypt Jas so once hash is
imported we could actually go ahead and
call the hash function passing in this
step password now one word of caution is
you’ve probably noticed that we’re using
a traditional function here and you
could see that by the use of the
function keyword if you were to use an
arrow function instead of a regular
function the scope inside this function
would actually be the outer scope in
this file and because we’re using es6
modules the strict mode is going to be
enabled by default and because of that
the this keyword inside an arrow
function is actually going to be
undefined in general if you’re working
in the outer scope and nodejs the
discord is gonna be a reference to the
global object and on the same note if
you’re working in a browser environment
this keyboard might be a reference to
the window object or once again if
you’re using a strict mode it’s going to
be undefined as well so long story short
this actually needs to be a regular
function I’m going to switch back to a
normal function and this way the this
keyword is actually going to refer to
the user that we’re working on so for
instance if we’re calling the create
method on the user model we’re creating
a user whatever user is being created or
instantiated that same user is gonna be
available inside of this hook so that’s
why it’s important to use a regular
function instead of an arrow function in
this use case so when we call this is
modified the is modified is actually
called on the model when we do this that
password the password is actually
accessed from the model instance so
whatever is being instantiated in this
call from user create passing the
arguments so once again this password
will be the exact same thing as arts
that password from our result in here
now the second argument would be the
salt so we can pass something like ten
or twelve I’m gonna pass in ten and this
call actually returns a promise so we
could do an awake on it in this case we
also need to put in the async keyword
and from the function but once we do the
results will be a new password and in
fact instead of assigning it to a
variable I’m just gonna assign it
directly to this that password so once
this is done we can actually go ahead
and call next now because the operation
of hashing a password might actually
fail what we might do instead is we
might take this piece of code in here
and we can actually put it inside of a
try-catch statement so if we catch an
error we could take that error and we
can basically do a next on it like this
otherwise we can put in the same logic
as before so once the password has been
hashed the model should be successfully
saved so let’s go back to the terminal
I’m gonna do Yonder what I’m gonna do is
I’m actually going to delete this user
because it has a plain text password I’m
gonna make sure
we don’t have that in our database Oh
back in the playground we can actually
go ahead and run the same query seems
like the user has been created so let’s
actually double-check that refresh the
page you can see that now we get a user
but if you expand the fields you could
actually see that the password is now
hashed so we’re not storing a plaintext
password instead we’re storing a hash of
that password and of course that’s going
to be used for authentication in
subsequent videos and now the only thing
is that back in our code over here we
don’t actually need to call next and I
didn’t realize it because we already
have a next call after the if statement
so actually we can either remove it from
here
but I think it’s better to keep it
because this is gonna catch all use
cases whether the password was modified
or not so we can actually remove this
call of next inside the try catch so if
the try succeeds is gonna go outside the
if and it’s gonna call next but if the
try fails it’s gonna go inside of the
catch and it’s gonna catch it with the
next call using the error object so this
is pretty much it for now now of course
there’s a huge topic of validation right
now we’re not validating the input
whatsoever so the user can actually put
in anything they want so they can put in
duplicate emails or duplicate usernames
they can even provide incorrect data
that doesn’t adhere to our business
logic so what do we need to do is we
need to figure out how to validate that
user input in our application so this is
the next topic we’re gonna work on in
the next video but for the time being
I’m signing off so this has been code
realm with myrn stack with graph QL
video series so hope you enjoyed this
video I’m gonna see you in the next one take care of

Please follow and like us: