MERN Stack Doctor Appointment Booking App Backend API Using Node Js, Express Js, MongoDB & JWT

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone in the previous two parts we completed the front-end development today we are diving into the back end of this project we will be building the server-side features that make our application come to life if you have not seen those parts yet I highly recommend checking them out first that will give the foundation for what we are about to do in this video so let's get started so I open BS code and go to the terminal server also I navigate to The backend directory CD backend and initialize the app with npm in it hit enter the package name let's say medical booking hit enter and continue author and yes this action clears our package.json file as you can see our package.json file is created with the name version description Etc next I'll install the required packages for this project so npm install or I Express for extras framework we need mongodb and so database interaction we need course to handle course origin issues just on a token for Authentication cookie Purser for handling cookies and Dot EnV to manage environment variables additionally I need big trip.js for password hashing and make sure to install Node 1 in your machine I have already installed nodemon globally so there is no need to install it again however if you have not installed node mod you should install first okay the installation might take some time while we wait for the installation to complete let's take a look at our schema as you can see this is our doctor schema the doctor schema contents the water Fields let me explain what is schema is his schema defines the structure of the data that will be stored for a doctor in the database to put it in perspective imagine you are filling out a form for a doctor you need their email for contact purpose first one to secure their account their name and other important information right okay at the end of the schema we have our model so what is a model think of it like a blueprint when building a house the schema serves as the design for student doctor information the model used to create read update and delete the doctor similar to placing furniture and decorating rooms in-house Now list the installation is done so I'll go to the pick is the Json file inside here set the type to module to enable modular Imports so type and it should be module additionally add the following Scripts so first one is start node index.js and the second one is start Dev for development server node mon index.js by using node mode on the Node just application will automatically restart whenever you make changes this saves you for manually stopping and creating the app every time you make a change okay so now let's create our entry point in the index.js file in this file we will set up our server so I'll create index.js first you have to import so import Express from Express then import cell from cookie version the next One Import course from course import mongos from Mongo's import dot EnV from Envy so now let's create dot ENB file and Define our port is equal to 5000 we will start using dot enb.config to load environment variables from the dot EnV file config and call the config function then we will create an app instance so const f is equal to express then let's define our Port is equal to process dot enb.port or 8000. for configuring course Behavior uh we will use the course option object so cost cost options is equal to an object and setting origin to true the origin true allows any domain to access the server's resources which is helpful during development in a production application you would want to restrict the allowed origin more strictly okay so now let's add a basic route to test our API so app.get and endpoint response request and response and I just simply send response as a message so let's just send API is working to test the server we have to listen the app right so app Dot listen first parameter will be our port and the next one will be called with function inside this callback I just simply console.log and server is running so let's run the server 10 pm start Dev s you can see our server is running on Port 5000. you can then access the API input by opening the root URL in your browser so I just go to browser and enter localhost a5000 as you can see that our API is working finally we will use middleware so app dot use and express digestion because we are going to purse this on data then we have to use cookie person the next one is app.use and course inside this course I have to pass the course option that we defined at the top okay let's now connect our mongodb database so I'll go to the browser and search mongodb Atlas click on this link and click on the sign in button if you don't have an account go to the sign up and create an account after login you will see an interface like this then click on this drop down and new project give a project name then click on next and create project then click on create select feature and click on create once your cluster is ready enter your username and password for the user and click on create user then give the IP address I just simply type in here 0.00.0 and click on ADD entry then finish and close now click on the connect button then drivers and copy the mongodb URL and close now go to the dot ENB file create URL variable with the mongodb URI you copied paste the copy copied link and replace the username and password okay then go to the index.js file let's connect our database so first we have to set strict way to force r otherwise it will warn the console so I just tried Mongo's dot set and strict query set to false okay now let's create our database connection function so const connecteddb [Music] is equal to async and our function body inside this function I will write a train catch block Mongoose dot connect and we have to pass the mongodb URL so the order will be process dot EnV Dot URL and pass the options just copy the options then paste in here simply console.log mongodb database is connected and if you uh if I get any error just simply console.log mongodb databases now we have to call this DB right connecteddb so I just call it in app.listen okay and now let's run as you can see mongodb database is connected if you get this message that's when your database is connected if you get a database connection field that means your database is not connected so make sure to connect it properly let's setting up controllers and routes to start we will organize our code create a folder named controllers and another named routes inside controllers let's make an auth controller.js file in here we will handle the registration and login logic so export const register is equal to async request and response then function body inside the function let's take a crypt try in case block we will have a function to handle registration we also create a similar function for user login so I just rename login now we need to connect these functions to specific URLs in the routes folder make an orthod.js here we will import Express from Express and we will import registration or register and logging function from auth controller.js file and make sure to a file extension is dot JS otherwise it will throw an error let's guess the router instance so const router is equal to Express dot router then router Dot path will be register and then our register function similar for login so where do we use post stickers here because when user register or login sensitive information like password email Etc the post required send the data in the request body which helps keep the sensitive data out of the URL and request logs making it less likely for the data to be exposed or intercepted so now let's use this route in our index.js file so import or throughout from routes and auth.js and then use app.use slash API slash version one slash auth and then alt route the line of code the app dot use slash API slash alt slash auth route is telling the application to use the auth route for any incoming HTTP request that match the slash API slash version one slash or slash register or slash API slash version one slash or slash login the router defined in the auth router will handle those requests executing an appropriate function all middleware associated with those routes now we have to export router so export default router and save the file now let's focus on registration and the structure the data from request.body so count something from request.body so the kind of data will be obtained from a requested body if I go to our front and Android start in here when someone registers we will get the name email password rule gender and photo so let's destructure these pieces of data from requested body email name roll photo sender so now let's take a variable let user is equal to null and we have to import user model from models then user schema.js and doctor from model slash doctor schema.js we also need json.oken so import JWT from just on a token and import from decrypt just before creating a new user we have to check if a user with the given email already exist or not in the database so we need to find user based on the provided email so if role is equal to patient then user dot find one and assign the user variable L save role is equal to patient the if condition code checks the role below to determine if the user is registering as a patient or a doctor it uses this rule to decide whether to interact with the user or doctor model in the database okay now let's check if user with the provided email is found so if user then simply return the response so return rest Dot status 400.json message let's say user already exist if no user is found we will create a new user but before getting we have to Hash the provided password for security using the Big Crypt uh JS okay 10. it generates a cryptographic salt a salt is a random value that is combined with the password before hashing the number 10 indicate the cost factor that determines the time taken to compute compute the hash you can give higher values but it will slow down the hashing process foreign first one is our password and second one is generated salt so now create a new user based on the role so if role is equal to patient user is equal to new user and we'll pass the user information similar for doctor so if role is equal to doctor then new doctor okay so this code will check if theological patient that will create any user inside the user model and if you if the rule is equal doc thought it will create a user uh in the doctor model okay so we created a news now we have to save so yeah right user dot save and we have to send a response or as dot status 200 .json success true and message let's say successfully created user successfully created and if uh we'll get any error let's send a response to test I open postman by the way you have to install postman on your machine so go to the browser and slash hostman I will get Postman official website they have a different operations operating system just install with your appropriate operating system to back to the postman I'll create a collection called Medicare booking now let's test our registration system the request will post an input is localhost Slash 5000 slash API version start then go to body click on a row and suggestion from the drop down and let's give user information so name email some random email password foreign click on the send button okay it's so user already exists this line is not an expected response that means we have a small mistake in the code so let's take the code okay so here is the problem I missed away because it's an async function and we have to avoid it so a weight now try again click on send as you can see we get the response user is created now let's check in the database so I go to the database and taking users collection because we give the rule is patient as you can see the user is created and Save in the database also user password is hashed let's now Implement logging system we start by extracting the email field and password from the incoming request body this is the user email address which they provide for authentication when logging inside try blocklets initialize the variable called user to null this variable will later hold the user information if found we perform to assign class queries to the database on two different collection one is for patient another is for Doctor we are looking for a user with the provided email in both collections now if we find a patient with a given email we assign the user variable to the to the patient similarly if if we find a doctor with the given email we assign the user variable to the doctor if no user is found so check if user exist or not so if not user who send a Json response so return I just copy and paste in here status 404 and message let's say user not found then we have to check if the provided password matches the hash password stored in the user object so const is password match is equal to gets command first compare password then we have to avoid be creeped dot compare the compare function takes two are going first one is provided password and second one is user password that stood in the database so password and user dot password foreign I just copy the status uh 400 and status false and message let's say invalid credentials if the password is matched then we will generate an authentication token so let's say I get token cost and will call a general token function we did not create the jet token let's create subconscious General token that we will receive user as a parameter and simply return JWT or Json of token.sign the first argument of jw.san is an object that contains the payload in this case we are indicating users ID and role in the payload object the second argument is just the create key used to sign in token so we will get the secret from dot environment variable foreign then crypto Dot random bytes than 256 dot to string and keep the base 64 as a string hit enter okay it will generate a secret key just copy and paste in here remove the quotation you don't need it okay so now now the third argument is an option object here we are setting the token expiration time to 15 days you can give any of days you want after that we restructure the user object to extract certain field it's a const ant something from user under foreign including the rest of the fields in the rest object finally we send adjacent response or status 200 success false or true success true message successfully login and we also passed that token data data and role if we get an error then we have to send status 500 and message failed to login now go to the postman and let's save the register endpoint for future use now we have to test our login functionality so keep the endpoint and it should log in go to the body row and select Json copy the provided email and password and remove name and Rule click on send but there is a problem with login we need to check the code let's make it capital letter foreign function in the compare function with the structure the password and passed in here but I don't know why it's not work like this so we have to pass the password like this and remember we to start the server because we changed the dot EMB file and it should be requested body save the changes and try again click on send now it should work as you can see we get our response with our token data role Etc let's create another user and check if login it marks so I just simply modify in here image should be John elderate gmail.com name let's say John password one two three four and click on send users successfully created now login email [Music] and password click on send it's all code now and if I go to the database as you can see we have two patient in the user collection okay let's dive into creating our user controller and routes so inside the controllers let's create a new file called user controller dot Js we'll start by importing our user from users schema.js now let's write a function to update the user so export const update user is equal to async request and response this function will take the user ID from the request parameters so const ID is equal to request dot parents dot ID and let's take a try in cash block instead of try block will update their information with the data provided in the request dot body so cost updated user is equal to await is a DOT find by ID and update pass the user ID and set the new value set and requested body and third parameter set the new to true the new true option ensure that we get the updated user information as a response and now send the response so as the status 200 dot Json success true message successfully updated and for error let's copy this line and paste inside case block response dot status 500 success false message let's say failed to update now just copy this function and paste it here two times and it will delete user and user dot find by ID and delete remove this lens and message fail to delete and this will get single user find by ID message let's say user found data should be user and 404 no user found copy this function one more time and this will get all user and instead of specifying a specific user we will simply pass an empty object that will find all the users from the user collection now for error message let's say not found let's define our routes so inside the routes directory create a user.js file and import updated user from usercontroller.js delete user get all user and get single user and we also need Express so import Express from Express now let's define our router so const router is equal to Express dot router then router dot get then slash colon and ID this is a dynamic route for getting a user by ID and then our get single user function just copy and it will just slash for getting all users get all user and for update user it will router.port and update user and it will delete and delete user and finally export default router now we need to use these routes in our main index.js file so inside here import use a route from Route slash user.js and use these routes so app.use slash API slash person one slash users and user router Let's test our endpoints using Postman so copy this URL and open a new tab and which should be slash API version slash user click on send oops we get an error it's look like I missed the dot JS extension in the user.js file let's fix that and try again this time we get our response but as you notice that we are sending sensitive data like password to the client which is not ideal we should exclude sensitive Data before sending the response right so how you can do that to do that go to go to the user controller and here add dot select and hyphen password which will exclude the password field okay so try again as you can see there is no password in the response let's also apply this to the single user route so just copy and Dot select and type in password to test copy the user ID and open a new tab input will be slash user then our user ID send a request and now we have removed the password from the single user response now let's update a user sends the method to Port and let's update a role and set to doctor click on send as you can see the role is updated now let's switch to doctor controller so copy all the code we have written for the user controller create a doctor controller.js file and paste it here rename the user function and variable to work with doctors and import doctors from doctor schema so I just select all Ctrl d Ctrl D Ctrl d and update all the user name to doctor now let's create a doctor dot JS file inside routes directory so doctor dot jazz copy this code and paste in here and rename all the user name to a doctor and use these doubts in index.js file doctor route from slash out slash doctor.js and app.use slash API slash talk thoughts and Dr Rao and let's rename the doctor file name okay now test a doctor in point in Postman in point will be doctor and click on send as you can see we get an empty array because we don't have any doctors to the doctor collection let's create a doctor so patients doctor and click on send now we have a doctor data in the get all of the function we find all the doctors and return to the clan right but in our front end we want to implement a search functionality to filter doctors by name and specialization right if someone searches then we want to Source search result data on the same page to do that we will use Query parameter from dot query so const query and request.query this parameter is used to filter data based on specific criteria now declare a variable called of thought that will hold the retrieved doctor records then check if the query parameter exists if it does will query to find only a probe doctor so doctor dot find is approved upload if I go to the doctor schema in here when someone registered as a Doctor by default it will pending and the admin manually checks and approves the doctor okay next we will match either the name or specialization based on the provided query stream or name object and Rejects query and options I the aura portal allows us to find doctors that match either the name or specialization and we use rejects operator with the option set to I for case a case intensive searching and same for specialization if query parameter does not exist we will find all approved doctor and exclude the password now let's test this in Postman click on send as you can see we get an empty area because we don't have any appropriate thoughts yet but if we remove the condition and try again now we get the data keep in mind that the doctor's status is pending so we will need to approve them to retrieve their information we'll implement this search functionality in our front when we integrate our API now we are moving into the crucial aspects of authentication and authorization before we dive into the code let's understand the problem we are trying to solve in Postman let's update the role and click on send notice that we change the role field and update it without any checks this means there is no authentication and anyone can modify user information but in real application each user should be able to update their own profile for that we need an authentication system to ensure that only the user who owns an account can access and modify their data similarly in the context of admin dashboard only authorized user showed access certain routes or perform specific action that's why authorization comes in let's start implementing this mechanism create a new directory called auth or and within it create a verified token.js file now let's import just another token from just on a token an import doctor from Dr schema an user from user schema now let's define the authenticate functions export const authenticate is equal to 18 this function takes three parameters request response and next the next parameter is a function used to pass control to the next middleware first we will retrieve the two can form authorization header in the request object const token is equal to request dot headers dot authorization we expect a token in the format like where are and then actual token then check if the token exist or not if not or token and not or token dot starts with wearer if it's not it returns and just understand 08401 status code so return response dot status four zero one dot Json success false message let's say no token authorization denied then try and guess the block insta try block we will verify the token for now let's log the token to see if it's work add token to actually use this authentication middleware go to the user route and apply it to the single user router import authenticate from auth slash verified token.js and use it in here now back in Postman try to get a user with a specific ID click on send and you will notice there is a node token error because we haven't added it yet to authenticate now let's login again copy the token go to the authorization Tab and select where to can and paste the token click on send and we get the response to check if our token is working let's uh take a look at the terminal as you can see our token with wearer now we need to extract the actual token value from this cons token is equal to we'll split the token from Bearer part to obtain the actual token value thank you now let's verify const decoded is equal to Json token dot verify and pass the token and process dot Envy dot secret key the very very function decodes the token using a secret key if the token is successfully verified we extract the payload which contains the user ID and role we add this to the request object so that subsequent middleware or route handlers can access this information and call the next function otherwise it will not work if any error occurs during token verification we enter the cache block and check if error.name is equal to token expired error it means that token has expired in our case we set a token to expired in 15 days remember so if it's expired we return a Json response with f 401 status code and message to cam is expired if the error is not related to the Token expiration it's likely a invalid token and we return Json response with 401 and Json success false and message invalid token now let's go back Postman again and this time try to access the user routes as you can see we can retrieve all the user because we are authenticated but we are not yet authorized in other words we want to protect this route and ensure that only the admin can extend it let's implement this security measure so export const restrict testing and request response next insert the function we'll start by extracting the user ID from the request object it's important to note that this ID is assumed to have been added by a previous authentication middleware next we will declare a variable call user foreign a user in both the user and Doctor collection using retrip user ID this tab helps us identify whether the user is a patient or a doctor and the user variable will assign to the respective user document once we have the user we will check if their role matches any of the rules specified in the rules array so if not rows dot includes user dot rows and this rules array is passed as a parameter to the function and making it a higher order function so rules and it's another function if the user role does not match any of the rules in the Ada will return a Json response with 401 status code and Json success false and methods you are not authorized if the user rule is authorized we call the next function to pass control to the next middleware now let's use this test strict middleware so import restrict form auth slash verified token.js after the authentication middleware we will apply the restrict modular and specify the rule we want to restrict access to in our case we want only admin users to access this route Let's test in Postman as you can see we now receive an unauthorized error because we are not an admin to access this route to secure all routes we'll need to use both authentication and rested middleware appropriately by integrating these mechanisms into our application we will ensure that only authorized users can access specific routes and perform actions this added layer of security is crucial for protecting sensitive data and ensure that our application functions as intended now let's dive into implementing a review system in our application to get started create a new file called reviewcontroller.js then import review from models slash review schema.js and doctor from Doctor schema first let's create the get all reviews function export const get all reviews is an async function request and response this function will be quite simple we will pass an empty object to it which will instruct the system to find all the reviews in our database a const reviews await review dot find and empty object and we'll send a response so let's just status two zero zero dot Json success true message successful data will be previous copy this line and paste inside cash flow status will be 404 success false message not found next let's create the create review function export cons create review async request and response first we will check if the request body contains a doctor field if it doesn't we will assign the doctor ID from the request parameters to the doctor field in the request body so request body dot doctor is equal to request Dot parents Dot doctor ID this ensured that the review is associated with the correct doctor we will do the same for the user ensuring that we know whose user is providing the review typically it's the currently authenticated user and we will get user ID from request once we have the necessary data we will create a new review and save it to the database new review and will pass the requested body let's rename this const saved review await new review dot say after saving the review we will update a doctor's document in the doctor collection so avoid doctor dot find by ID and update request dot body dot doctor and especially we will push the ID of the saved review into the reviews array of the doctor's document so pause reviews and saved review dot underscore ID this way we can easily access and populate the review information for a specific doctor it establishes a clear relationship between the doctor and the reviews if everything goes well we'll send a Json response with a 200 status code back to the client to confirm that the review has been created successfully so message review submitted and for error status will be 500 success false message error Dot message now let's define the review route create a review.js file inside the routes directory and import Express from Express import get all reviews from controller slash review controller.js and create review import authenticate from verified token.js and restrict now let's create router instance so const router is equal to Express dot router and router dot route puzzle slash and Dot get all reviews and for key attributes it will be post and authenticate for authentication restrict and Export default router and we need to use these routes inside our index.js file so import review route from route review.js and we will use in here reviews and reviewed out one thing to notice in the review route is that the route is simply slash but when we create a review we need to associate it with a specific doctor such as Doctor slash doctor ID slash reviews right to achieve this we will use a nested route to set up this nesting go to the doctor's route import review router from review.js and then router dot use modular function this function configures a nested route it tells our application to use the review router to handle routes that are prefixed with doctor ID slash reviews these structures ensure that all routes related to doctor reviews are nested under a specific doctor's ID allowing us to associate reviews with specific doctors however in the review router we currently don't have access to the doctor ID to enable this access we will use merge params true in them review router this option ensures that parameters such as Doctor ID from the parents route are accessible in the nested routes Handle by review router now let's create a review using Postman but before creating less space dog thoughts okay we are in counter an issue where there are node a producers make sure to approve a doctor in mongodbia class an update let's try again now we get doctor info copy the ID open a new tab give the endpoint doc thoughts slash doctor ID slash reviews the method will be post body row and select Json review text go doctor and writing let's say file click on send we are getting error not token so let's login copy that token go to the authorization select better token press the token and try again click on send now we are getting the our response and the review is created and as you can see in the doctor document we have our review ID to enhance our review system let's also populate the user information of the person who provided the review this will allows us to display user details in our front end we can achieve this with the modular function called Ruby schema dot pre we can achieve this with the modular function that executes before any query string with the prefix find so they start populate path will be user and user refers to this user inside review schema and select we just need name and photo this modular function is used to populate user information in the review it gets executed each time a query for reviews is made by using the populate method we Face an add user information such as name and photo to the review document and at the end we need to call the next function then we also populate and our doctor controller so populate and we need we want to copulate reviews now let's create a new review as you can see our review is created this is the complete implementation of our review system now when user provides reviews we can associate them with specific doctors and in our front end we'll have access to user details associated with each review let's now calculate average rating and total rating to do that we will use a useful method called Statics in mongodb so review schema dot Statics dot calculate average is an async function it will receive doctor ID as a parameter for calculating average ratings and total we will use mongodb aggregation pipeline so const ants is equal to a weight this dot aggregate in here this refers to the current review so what mongodb aggregation pipeline is the mongodb aggregation on Pipeline is like a set of data processing steps for longevity databases it lets you filter group sort and transform your data to get the information you need in the aggregate function it first message reviews associated with the specific doctor so maths and doctor doctor ID then it groups the reviews based on the doctor's ID the group object ID then it calculates the number of ratings using some operator number of rating sum and it also calculate average ratings using average operator console.log stats to see the data okay to see the data we need to call the calculate average ratings so review schema Dot post save and function inside this function they start Constructor dot calculate average ratings and we'll pass the distort doctor the review schema dot post it's the middle function that part of the code is executed after a review document is saved it costs the calculate average dating's method of the Constructor model associated with RB schema it passes the doctor value from the review document which represents the doctor's ID to the calculate average ratings for that doctor to test let's get a new review let's say good experience click on send review is created now let's see in the console as you can see we get our state with number of ratings and average ratings so now let's get another review and this time letting one and review text click on send now as you can see our average rating is decreased now we have to update the specific doctor document with the number of ratings and average ratings so avoid dog Thor schema we need to import doctor from Doctor schema and I just remove this schema okay so doctor dot find by ID and update Dr ID and we will update total rating and our resulting a total rating and we'll get the value from stats 0 index and Dot number of rating and average rating that index 0 dot average rating all right that wraps up the development of our API for today we have covered a lot of ground building various features like user management doctor profiles authentication and authorization and even a review system the only feature left on our checklist is booking and that's something we will take all at the end of this project but before we bring this video to a close I would love to hear your thoughts please share your opinions and feedback in the video description below your input is invaluable as it helped us to create content and if you find this video helpful and informative don't forget to hit that subscribe button give a thumbs up and share it with your fellow developers your support motivates us to continue creating content that Imports you on your coding Journey thank you so much for joining us today stay tuned for the next part of this project
Info
Channel: Coding With Muhib
Views: 19,678
Rating: undefined out of 5
Keywords: mern stack project, mern project, mern stack, reactjs, nodejs, mern stack projects for resume, mern stack app, mern booking project, mern booking app tutorial, booking app, doctor appointment booking, doctor appointment booking website design, react booking system, booking website, mern tutorial, coding with muhib, codingwithmuhib, react tutorial, jwt, authentication in node js, authentication and authorization in node js using jwt, node js tutorial, mongodb tutorial, express js
Id: H6g_VtblMh8
Channel Id: undefined
Length: 89min 2sec (5342 seconds)
Published: Thu Sep 07 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.