So, let's continue working
on the back end of authentication
and for this,
back here in our code,
we of course wanna start
by taking a look at the auth.controller,
here we have to get signup function
for serving that signup page,
but of course in order to handle
the submission of this form,
we now also wanna add a new function,
maybe right below it
though the exact position doesn't matter,
which could be called signup,
the name is up to you
but you typically wanna describe what's happening
when this function is called
and this should be a function,
a controller action that will be executed
when a user is created,
when a user signs up.
Here of course we still get request
and response because we still have a middleware
function here in the end
and I wanna expose that outside of this file,
so I'll make it available under a key named signup
in my exported object.
Now we come back to this function as second,
for the moment,
I wanna go to my routes,
to the auth:routes
and add a new route here for handling this,
now this will not be a get route,
because I don't wanna handle a get request,
instead it is quite common to use
post requests for things like signing up users,
basically whenever you create data on the server,
whenever you manipulate data on the server,
you wanna use a post request
instead of a get request,
so therefore you're all
to find a post route,
the path can still be signup though
and it's okay to have two routes
with the same path,
as long as they have different HTTP methods they handle
and here I then point at auth controller signup,
which is this newly added function I added
a couple of seconds ago.
Now, of course we need to ensure
that such a post request to /signup
is being sent when the form is submitted
and therefore in our signup.ejs file
where we have the form,
we now need to set the action
and method of that form,
because with the action we control
where a request is sent to,
automatically by the browser,
with method we define which kind
of request is sent,
now the where is /signup
and this ensures that we simply target
our current domain/signup,
the method for forms has to be get or post
and as mentioned a couple of seconds ago,
we typically wanna go for post,
this also has the advantage that post requests
unlike get requests
can have a post body,
a request body,
which can contain extra data,
which you wanna submit,
with get requests we can also submit data
with help of query parameters
as you saw before in the course,
but this is less common
and simply not recommended
when you are about to store data on the back end,
so post it is.
Now, with that this signup.ejs file
is properly configured,
the route was added,
now we just have to work on that controller
and in this controller function,
the signup function,
I now of course wanna in the end
validate all the incoming user data,
see if it's correct
and if we maybe already have a user with that email,
and ultimately if we made it through
all the validation,
I wanna create a user
and store that user in that database,
and that's the keyword,
database, before we start writing any logic here,
we wanna make sure that we're able to connect
to a database
and you can of course build this kind of website
with both a SQL based database like MySQL
or a no sequel database like MongoDB,
I will go for MongoDB here
because it's a bit closer to JavaScript
syntax wise,
which can make it a bit easier to work with
and we've been working with it
a lot throughout the course,
so we probably got more practice with it,
nonetheless, definitely feel free to also build
a version of this project where you use SQL
and MySQL instead,
both will work.
Now, you wanna ensure that you got MongoDB
installed to continue
and of course we did install it earlier in the course,
if you skipped those sections,
I do recommend that you go through them,
you wanna install the community server in the end,
so even if you don't go through these sections,
you can of course also install it
with help of the official docs
where you can also learn how to install
MongoDB on different operating systems,
it's the Community Edition which we need,
once you did install it,
you also need to start it,
you learned about that earlier in the course
and you'll also find instructions on this here
in the official docs
and once you started it,
here I have it running in a separate terminal window,
we are ready to connect to it,
now for connecting to it
and for managing a pool of connections,
I will create a separate file
and actually a separate folder
which we'll name data or database,
in which I'll add a database.js file
and this file will hold the logic
for connecting to MongoDB,
however I still don't wanna write
all the logic on my own,
I instead will install a third-party package
which we have also used a lot in this course,
the MongoDB package,
which helps us with establishing
and managing that connection,
so npm installed MongoDB
and once that is installed,
in this newly added database.js file,
we can import MongoDB by requiring it in there
and this MongoDB package will give us
a lot of utility methods
that make working with a database easier,
because here with that required now,
as a next step,
I will create a MongoClient by using
mongodb.mongoclient, whoops.
MongoClient like this
and then we can use this MongoClient
to call the connect static method on it,
so we don't need to instantiate MongoClient,
we can call connect on it like this
and connect then takes the URL to our database,
and with a locally installed MongoDB database server,
that is localhost:27017,
that's the default port occupied
by the MongoDB server.
Now, connect returns a promise
and you learned about promises,
these are objects which will eventually
resolve to a certain value
and they are often used in situations
where you have an asynchronous operation,
so an operation which may take a bit longer
and which therefore runs side by side
with your AVer code
and which eventually then completes,
and we can handle such promises
with help of the then method
which we can call on the promise object,
or a bit more convenient with async await,
for this we just need a separate function,
which I would need anyways here though,
which could be called connectToDatabase
and this function can be decorated
with the async keyword,
this then unlocks the await keyword
inside of this function
and now if I call MongoClient.connect
instead of this function,
we can await this
and what we'll get back is a client object
which has internal information
about the established connection,
now I want to use this client
in various places of my project here
and hence,
I'll add a database variable,
which initially is undefined
and in the end,
in this database variable,
I'll store client.db,
which is a built in method,
which we can call on this client object
to connect to a certain database
and here I'll choose online-shop
as a database name,
as we learned in this course
when working with MongoDB,
you don't have to create databases ahead of time,
instead you can simply use any database of your choice
and it will be created for you
the first time you enter data if it doesn't exist yet
and it's then the connection to this concrete database
which is stored in this database variable
and I'm using this variable
because I'll add a second function,
getDb where I actually will check
if we maybe don't have a database yet,
in which case,
I'll generate a custom error,
we can throw section error
with the throw keyword
and that will crash the application then
or at least generate an error
which we can handle in some other place,
if we try to access the database
without connecting to it first,
which shouldn't happen here
but which could happen
and I'll create a new error object
with new error,
using the built in error clause,
or constructor function which is built into JavaScript
to generate an error object
and to then throw this generated error object,
and to this error constructor function,
you can pass a error message string like,
'You must connect first!'
So, now that's an error I will throw
if we try to get access to the database
without establishing the connection first,
if we make it past the safe check,
which we normally should,
I will return a handle to that database
and then ultimately I want access to these functions
from outside this file,
so I will export an object,
an object which has a pointer at connectToDatabase
using connectToDatabase as a key
and which has a pointer to getDb using getDb as a key,
so that's my database.js file.
This database.js file will now be used
in my app.js file
because there I wanna establish a connection
to the database right when I'm starting my web server
and I don't wanna start my web server
if establishing that database connection failed,
so here in app.js we can start by importing
this database object,
by requiring ./data/database
and then here at the bottom
where I call app.listen,
I will now simply call db.connectToDatabase
and this then yields a promise
simply because in database.js,
connectToDatabase is an async function
and any function decorated with async
will automatically always yield a promise,
even if you don't return a promise yourself,
I don't have any return statement in there,
nonetheless, async functions will always
return a promise automatically
and therefore in app.js,
where I call connectToDatabase,
this will yield a promise
and then here we can add then
to execute code if that promise succeeded
or a catch if that promise failed
if we had an error in there for example
and we could get an error if connecting
to the database fails.
Now, in that error case,
I'll define an anonymous function
which gets that error object,
which is generated automatically by the MongoDB package
if establishing the connection failed
and then I'll just
console.log('Failed to connect to the database!')
and after that I'll also console log the error object
so that we can see more details about the error as well.
Now, in the then case that we succeeded,
here I actually will also define an anonymous function
and in here I just want to call app.listen(3000),
so this code down there
to only startup the web server
and start listening on port 3000
if we connected to the database successfully,
with that we should be establishing a database connection
whenever we start this server,
so now since I shutdown the server before anyways
in order to install the MongoDB package,
we can restart it with npm start
and it crashes here for me,
invalid connection spring
and yes the reason is a mistake
in database.js in this URL,
the correct URL to a locally installed
MongoDB database is localhost:27017,
but we have to prefix this with mongodb://,
that's the actual URL,
the MongoDB package wants,
so if we now save this,
this now restarts
and now we have that running server
which is connected to a database.