I did finish refactoring
the authentication part for me here,
though I will say, as I said before,
there's always more you can do.
I try to strike the balance
between doing enough refactorings
and still not changing everything,
and therefore ensuring
that the code can still be recognized.
So what did I do?
I added the auth-controller,
and I renamed the post-controllers.js file
to post-controller
because now that we have more than one file,
it's a bit clearer to see
the actual functions are not the controllers.
These are the actions of your controller instead.
Instead, it's the controller files
and the groupings of the functions
that act on a certain feature
like the blog or like the auth part
that makes up a controller.
And therefore, here we have a blog controller
with all those actions that are related to posts,
and I have an auth-controller
with all these functions, these actions,
related to authentication.
That's why I renamed these files.
And therefore, in the routes, of course, in blog.js,
I'm also now using the blogController,
I renamed this as well and changed my import path,
and I'm doing the same in auth.js.
This is now also a cleaned-up routes file
where I'm using this auth-controller,
and all these functions, these route handler functions,
now became controller actions,
so functions in the controller.
Now let's take a look at the auth-controller.js file.
It's still a relatively big file
because login and signup are a couple of steps
that have to be executed after each other,
and I'm still performing these main steps
in auth-controller.js.
But I got rid of the database import
because I moved all the database-related logic
into a user model.
You could have named it auth as well,
but I think the actual entity
with which we're working is a user.
Now, in that user model, I have the constructor function
that takes the email and password
of the user we are working with.
And then I got a couple of functions
that help during the login process
like getUserWithSameEmail.
Here I can simply check if I find a user
with the email of the user I created here,
and then I return that user.
And I use this function in existsAlready, for example,
which is a little utility method I added to the user model
to look for a user with the same email address
using that method up here,
and then I just return true or false
depending on whether we found one or not
so that I don't have to perform this check
in the controller,
but instead there, I can just call
this existsAlready utility method.
And we'll see it being called in a second.
Then I have the signup method
where I hash the password and then write the user data
with the hashed password and the provided email
into the database.
And I have the login method where I compare passwords,
and then I return the result of that comparison.
That's all I'm doing there because the entire validation,
sending validation errors, and adjusting the session,
all these parts are still done in the controller here,
though you could also consider outsourcing those
into the model
or probably into some utility helper files instead.
Now, in that auth-controller.js file,
I therefore still have these different actions,
these different functions,
and I'm still using the approach where I get error data
from a session, for example, with some default data
in case I have no errors.
I do the same for login.
There, I just don't have my confirm email default field.
And I then have my signup function, my signup action,
where I check if the user credentials are valid.
I outsource this logic into a separate validation.js file.
There, I inverted the logic.
It's not a must-do,
but it is often considered a better practice
to write these validation function names in a positive way,
so isValid instead of isNotValid,
and therefore you then wanna return the appropriate result,
but ultimately it's not a must-do.
But here I inverted the logic,
and I hence return true if the user credentials are valid,
and I return false otherwise.
In addition, back in the auth-controller,
I'm using the result of this function call,
and then I flash my error data to the session
if I do have errors,
and I define my action that should be performed
after the data has been flashed onto a session.
And then if we don't have an error,
I continue by using my User model to create a new user
with the entered email and password.
I don't need to confirm password here
because I only need that for validation.
Here I'm using it.
And when I create a new user,
I then call that existsAlready utility method
I showed you a couple of seconds ago,
and I await this because it's a async method,
and I use that in this if check
to flash errors if we already have a user with that email.
Otherwise, we proceed and we sign the user up,
which means we store it in the database
with the hashed password.
Now, the login function is not too different,
but there I start with creating a new user
with the entered email and password.
And I then call that function
for getting an existing user with that email,
and then I check if we don't have an existing user
in which case I flash some errors.
Otherwise, I continue and I call login
which, as I showed you, internally then compares passwords,
and hence I return the result of that comparison.
And if it's not a success, I flash some errors.
Otherwise, I continue, and then here I update my session
with the isAuthenticated data and so on,
and the logout function hasn't changed at all.
Again, you could consider outsourcing
the session changing logic
into a separate utility file or function,
but here I kept it in the controllers
so that I don't change too much in one go.
With that, however,
everything still seems to work just fine.
I get errors if I use incorrect credentials.
And on the other hand, with correct credentials,
I can log in and log out, and that all works.
And therefore, that is some basic refactoring
which we can use.
We're also using the MVC pattern,
and you hopefully see what the idea behind it is,
that we group our database-related logic into such a model.
And with that, we improved the structure of this project.
And whilst this module therefore
was a lot about moving things around
and not about too many new features,
this, as I mentioned at the beginning, is a vital part
of being a developer.
You need to be able to keep your code organized,
and you will always refactor your code
because you will never write the final code
right from the start.
Instead, you need to be willing to refactor your code,
reorganize your code,
and therefore ensure that it stays manageable.