- This Project follows Model-View-Controller (MVC) pattern.
- Controller folder: This folder contains the controller files. It handle the logic for processing requests, interacting with models, and preparing the data to be sent back to the client.
- Model folder: This folder contain the model files. Models represent the data structures or entities of your application.
- Routes folder:: This folder contain the model files. Models represent the data structures or entities of your application. The routes folder contains the route files, which define the endpoints and their associated controllers. Routes handle the incoming requests and direct them to the appropriate controller method based on the URL and HTTP method. They serve as the entry point for requests and establish the mapping between URLs and controller actions.
To set up the backend locally, follow these steps:
-
Clone the repository
git clone <repository-url> -
Install dependencies Navigate to the project root directory and run the following command to install the required dependencies:
npm installThis will install all the dependencies listed in thepackage.jsonfile. -
Configure environment variables To configure environment variables when the
.envfile is located in the config folder, you can follow these steps:
- Create the .env file
Create a file named .env in the config folder of your project. create a folder named
configand inside it create your.envfile. - Define environment variables
Inside the
.envfile, define the necessary environment variables. Here's an example:
DB_URI=<your-database-connection-string>
JWT_SECRET=<your-jwt-secret-key><br>PORT = 4000
JWT_EXPIRE = 5d
COOKIE_EXPIRES = 5
COOKIE_EXPIRES = 5
MONGO_URL = <your_db_url>
SMPT_MAIL=vetmedman501@gmail.com
SMPT_PASSWORD =<password>
SMPT_HOST=smpt.gmail.com
FRONTEND_URL = "http://localhost:3000"
- Start the backend server
To start the backend server in development mode with automatic restart on file changes, run the following command:
npm run dev
-backend
/controllers
| - /categories
|- animalController.js
|- dailyEssentialController.js
|- medicalTypeController.js
|- TreatmentTypeController.js
| - oderController.js
| - productController.js
| - userController.js
| - varietyController.js
/database-Connection
| - database.js
/middleware
| - auth.js
| - catchAsyncError.js
| - error.js
/models
| - /categories
|- animal.js
|- dailyEssential.js
|- medicalCareModel.js
|- treatmentModel.js
| - oderModel.js
| - productModel.js
| - userModel.js
| - varietyModel.js
/routes
| - /categories
|- animalTypeRoutes.js
|- dailyEssentialRoutes.js
|- medicalCareRoutes.js
|- treatmentTypeRoutes.js
| - oderRoutes.js
| - productRoutes.js
| - userRoutes.js
| - varietyRoutes.js
/utils
.gitignore
app.js
server.js
-package.json
-package-lock.json
The userModel.js file contains the definition of the User model, representing the user data structure in your application. It provides the schema and methods for working with user data in the database.
- Schema Field
name,email,password,role,createdAt,resetPasswordToken-Token used for password reset.,resetPasswordExpire- Expiration date for the reset password token. Hookspre("save")- This hook is executed before saving the user to the database. It checks if the password field is modified and hashes the password using bcrypt if it is.
- Methods
-
getJWTToken(): - his method generates and returns a JSON Web Token (JWT) for the user. The JWT includes the user's ID as the payload. -
comparePassword(enteredPassword)- This method compares the entered password with the stored hashed password and returns a boolean indicating if they match. -
getResetPasswordToken- This method generates a random token for password reset, hashes it, and adds it to the resetPasswordToken field. It also sets the expiration date for the token.
-
The Product model represents a product in the application. It defines the schema for storing product-related information in the database.
Note:- Go to product Model to see all the entities. Here lrt's discuss some important one
ratings:{
type:Number,
default:0
},
//This is for whole ratings of a single product.
e.g - if 2 user added rating for a single product then ratings will show the avg of 2 user's rating.
reviews:[
{
user:{
type:ObjectId, // ObjectId (reference to "User" collection, required)
ref:"User",
required:true
},
name:{
type:String,
required:true,
},
rating:{
type:Number,
},
comment:{
type:String,
}
}
],
// This is to include the review of a single user for a single product
// the rating in review is for a single user.
Schema Fields
-
shippingInfo: The shipping information for the order.
- Fields:
fname: The first name of the shipping address.- Type: String
- Required field
lname: The last name of the shipping address.- Type: String
- Required field
address: The address for shipping.- Type: String
- Required field
OptionalAddress: Optional additional address information.- Type: String
farmAddress: Farm address.- Type: String
city: The city for shipping.- Type: String
- Required field
state: The state for shipping.- Type: String
- Required field
country: The country for shipping.- Type: String
- Required field
pinCode: The PIN code for shipping.- Type: Number
- Required field
phoneNo: The phone number for shipping.- Type: Number
- Required field
- Fields:
-
billingInfo: The billing information for the order. It has the same structure as the
shippingInfofield. -
orderItems: The items included in the order.
- Type: Array of objects
- Fields:
name: The name of the ordered item.- Type: String
quantity: The quantity of the ordered item.- Type: Number
- Required field
image: The image associated with the ordered item.- Type: String
- Required field
product: The reference to the "Product" collection representing the ordered product.- Type: ObjectId
- Reference: "Product" collection
- Required field
varieties: Array of strings representing the varieties of the ordered product.
-
user: The reference to the "User" collection representing the user who placed the order.
- Type: ObjectId
- Reference: "User" collection
- Required field
-
orderedAt: The timestamp indicating when the order was placed.
- Type: Date
- Required field
-
orderStatus: The status of the order.
- Type: String
- Required field
- Default: "Processing"
-
deliveredAt: The timestamp indicating when the order was delivered.
- Type: Date
-
createdAt: The timestamp indicating when the order was created.
- Type: Date
- Default: Current timestamp when the order is created.
The Order model is exported as a Mongoose model named "Order" for use in other parts of the application.
The Variety model represents the variations or options available for a product in the application. It defines the schema for storing variety-related information in the database.
-
subProduct: The sub-products or categories of the variety.
- Type: Array of strings
-
Length: The available length options for the product.
- Type: Array of strings
-
Coating: The available coating options for the product.
- Type: Array of strings
-
Sterility: The available sterility options for the product.
- Type: Array of strings
-
Quality: The available quality options for the product.
- Type: Array of strings
-
colors: The available colors for the product.
- Type: Array of strings
-
sizes: The available sizes for the product.
- Type: Array of strings
The Variety model is exported as a Mongoose model named "varieties" for use in other parts of the application.
The Animal Type model represents different types or categories of animals in the application. It defines the schema for storing animal type-related information in the database.
-
animalName: The name of the animal category.
- Type: String
- Trimming: Removes leading and trailing whitespace
- Required: Must be provided
- Maximum length: 30 characters
-
imageUrl: The URL of the image associated with the animal category.
- Type: String
-
user: The user who created or manages the animal category.
- Type: ObjectId
- Reference: "User" model
- Required: Must be provided
The Animal Type schema includes timestamps, which automatically add the following fields to the documents:
- createdAt: Indicates when the document was created.
- updatedAt: Indicates the last time the document was updated.
The Animal Type model is exported as a Mongoose model named "Animal" for use in other parts of the application.
The Essential Type model represents different types or categories of essentials in the application. It defines the schema for storing essential type-related information in the database.
The Medical Type model represents different types or categories of medical care in the application. It defines the schema for storing medical care type-related information in the database.
The Treatment Type model represents different types or categories of treatments in the application. It defines the schema for storing treatment type-related information in the database.
-
createAnimalType: This function creates a new animal category. It checks if the
animalNamealready exists in the database (case-insensitive). If it exists, it returns an error message. Otherwise, it creates a new animal category using theAnimalmodel with the providedanimalName,imageUrl, anduser(fromreq.user.id). It responds with a success message and the created animal category. -
allAnimalType: This function retrieves all animal categories from the database using the
Animalmodel. It responds with a success message and an array of animal categories. -
updateAnimalType : This function updates an existing animal category. It finds the animal category by its ID (
type_idparameter) and updates it with the data fromreq.body. The{ new: true }option ensures that the updated animal category is returned as the response. It responds with a success message and the updated animal category. -
deleteAnimalType: This function deletes an animal category. It finds the animal category by its ID (
type_idparameter) and removes it from the database. It responds with a success message and the deleted animal category.
-
Create Essential Type: This function creates a new essential category. It checks if the
essentialNamealready exists in the database (case-insensitive). If it exists, it returns an error message. Otherwise, it creates a new essential category using theEssentialmodel with the providedessentialName,imageUrl, anduser(fromreq.user.id). It responds with a success message and the created essential category. -
Get All Essential Types: This function retrieves all essential categories from the database using the
Essentialmodel. It responds with a success message and an array of essential categories. -
Update Essential Type: This function updates an existing essential category. It finds the essential category by its ID (
type_idparameter) and updates it with the data fromreq.body. The{ new: true }option ensures that the updated essential category is returned as the response. It responds with a success message and the updated essential category. -
Delete Essential Type: This function deletes an essential category. It finds the essential category by its ID (
type_idparameter) and removes it from the database. It responds with a success message and the deleted essential category.
-
Create Medical Care Type: This function creates a new medical care category. It checks if the
medicalCareNamealready exists in the database (case-insensitive). If it exists, it returns an error message. Otherwise, it creates a new medical care category using theMedicalmodel with the providedmedicalCareName,imageUrl, anduser(fromreq.user.id). It responds with a success message and the created medical care category. -
Get All Medical Care Types: This function retrieves all medical care categories from the database using the
Medicalmodel. It responds with a success message and an array of medical care categories. -
Update Medical Care Type: This function updates an existing medical care category. It finds the medical care category by its ID (
type_idparameter) and updates it with the data fromreq.body. The{ new: true }option ensures that the updated medical care category is returned as the response. It responds with a success message and the updated medical care category. -
Delete Medical Care Type: This function deletes a medical care category. It finds the medical care category by its ID (
type_idparameter) and removes it from the database. It responds with a success message and the deleted medical care category.
-
Create Treatment Type: This function creates a new treatment category. It checks if the
TreatmentTypeNamealready exists in the database (case-insensitive). If it exists, it returns an error message. Otherwise, it creates a new treatment category using theTreatmentmodel with the providedTreatmentTypeName,imageUrl, anduser(fromreq.user.id). It responds with a success message and the created treatment category. -
Get All Treatment Types: This function retrieves all treatment categories from the database using the
Treatmentmodel. It responds with a success message and an array of treatment categories. -
Update Treatment Type: This function updates an existing treatment category. It finds the treatment category by its ID (
type_idparameter) and updates it with the data fromreq.body. The{ new: true }option ensures that the updated treatment category is returned as the response. If the treatment category is not found, it returns an error message. It responds with a success message and the updated treatment category. -
Delete Treatment Type: This function deletes a treatment category. It finds the treatment category by its ID (
type_idparameter) and removes it from the database. If the treatment category is not found, it returns an error message. It responds with a success message and the deleted treatment category.
-
newOrderfunction: This function is used to create a new order.- It extracts the required information from the request body, such as
shippingInfo,orderItems, andbillingInfo. - It creates a new order using the
Order.createmethod, passing the extracted information along with the current date and the user ID from the request. - It sends an email to the user with the order details using the
sendEmailfunction. - Finally, it sends a JSON response with the created order.
- It extracts the required information from the request body, such as
-
getSingleOrderfunction: This function retrieves a single order by its ID.- It uses the
Order.findByIdmethod to find the order with the specified ID and populates theuserfield with the corresponding user'snameandemail. - If the order is not found, it returns an error.
- Otherwise, it sends a JSON response with the retrieved order.
- It uses the
-
myOrdersfunction: This function retrieves all orders for the logged-in user.- It uses the
Order.findmethod to find orders where theuserfield matches the ID of the logged-in user. - It sends a JSON response with the retrieved orders.
- It uses the
-
getAllOrdersfunction: This function retrieves all orders (for admin use).- It uses the
Order.findmethod to find all orders. - It calculates the
totalAmountby summing up thetotalPriceof each order. - It sends a JSON response with the total amount and the retrieved orders.
- It uses the
-
updateOrderStatusfunction: This function updates the status of an order (for admin use).- It uses the
Order.findByIdmethod to find the order with the specified ID. - If the order is not found, it returns an error.
- It checks if the order status is already "Delivered" and returns an error if it is.
- It updates the stock of each product in the order by calling the
updateStockfunction. - It updates the order status based on the
statusprovided in the request body and sets thedeliveredAtfield if the status is "Delivered". - It saves the updated order and sends a JSON response.
- It uses the
-
updateStockfunction: This function updates the stock of a product.- It takes the product ID and quantity as parameters.
- It retrieves the product using the
Product.findByIdmethod. - It subtracts the quantity from the product's
Stockproperty and saves the product.
-
deleteOrderfunction: This function deletes an order (for admin use).- It uses the
Order.findByIdAndRemovemethod to find and remove the order with the specified ID. - If the order is not found, it returns an error.
- If the order is found, it sends a JSON response indicating success.
- It uses the
-
createProduct: This function is used to create a new product. It receives the product data from the request body, sets theuserfield to the current user's ID, creates a new product using theProductmodel, and returns the created product as a JSON response. If an error occurs, it calls thenextfunction with the error. -
getProductDetails: This function retrieves the details of a single product. It takes the product ID from the request parameters, finds the product using theProductmodel, and returns the product details as a JSON response. If the product is not found, it calls thenextfunction with an error. -
updateProduct: This function is used to update a product. It first finds the product using the provided ID, then updates the product with the new data from the request body using theProduct.findByIdAndUpdatemethod. It returns the updated product as a JSON response. If the product is not found, it calls thenextfunction with an error. -
deleteProduct: This function deletes a product. It finds the product using the provided ID and removes it using theProduct.findByIdAndRemovemethod. It returns a JSON response indicating the success of the deletion. If the product is not found, it calls thenextfunction with an error. -
showAllProducts: This function retrieves all products with optional filters and pagination. It allows filtering bykeyword,animal,treatment,dailyEssential, andmedicalCare. The filters are applied to theProduct.findquery to retrieve the matching products. The results are paginated using thepageandpageSizeparameters. The function returns a JSON response with the count of total products, the current page, the number of pages, and the retrieved products. If an error occurs, it calls thenextfunction with the error. -
createProductReview: This function allows users to create or update a review for a product. It receives the review data from the request body, including the rating, comment, and product ID. It checks if the user has already reviewed the product and updates the existing review or adds a new review accordingly. It calculates the average rating for the product based on all reviews and updates theratings,numOfReviews, andreviewsfields of the product. It returns the created or updated review as a JSON response. -
getProductReviews: This function retrieves all reviews for a product. It takes the product ID from the request query parameters, finds the product using theProductmodel, and returns the reviews as a JSON response. If the product is not found, it calls thenextfunction with an error. -
deleteReview: This function allows users to delete their review for a product. It takes the product ID and review ID from the request query parameters. It finds the product using the product ID, filters out the specified review from the product'sreviewsarray, recalculates the average rating and number of reviews, and updates the product usingProduct.findByIdAndUpdate. It returns a JSON response indicating the success of the deletion. -
getAdminProducts: This function is specifically for administrators. It retrieves all products using theProduct.findmethod and returns them as a JSON response.
-
Importing required modules and files:
ErrorHandler: A custom error handling utility.catchAsyncErrors: Middleware function to catch asynchronous errors.User: The user model for interacting with the database.sendToken: Utility function to send a JWT token as a response.sendEmail: Utility function to send emails.crypto: Node.js crypto module for generating password reset tokens.logger: Custom logger utility for logging messages.
-
Registering a User (
registerUserfunction):- Create a new user in the database using the provided name, email, and password.
- Send a JWT token as a response.
-
Logging in a User (
loginUserfunction):- Check if both email and password are provided.
- Find the user in the database based on the provided email.
- Compare the provided password with the user's stored password.
- Send a JWT token as a response if the credentials are valid.
-
Logging out a User (
logoutfunction):- Clear the JWT token cookie in the response.
- Send a success message.
-
Forgot Password (
forgotPasswordfunction):- Find the user based on the provided email.
- Generate a password reset token and set an expiry time for it.
- Save the user with the reset token and expiry time.
- Send a password reset email to the user with the reset token URL.
-
Reset Password (
resetPasswordfunction):- Verify the reset token from the request parameters.
- Find the user with a valid reset token and not expired.
- Update the user's password with the new password from the request body.
- Clear the reset token and expiry time.
- Send a JWT token as a response.
-
Get User Details (
getUserDetailsfunction):- Find the user details based on the user ID from the JWT token.
- Send the user details as a response.
-
Update Password (
updatePasswordfunction):- Verify the user's current password.
- Check if the new password matches the confirmation password.
- Update the user's password with the new password.
- Send a JWT token as a response.
-
Update User Profile (
updateProfilefunction):- Update the user's name and email based on the request body.
- Send a success message and the updated user profile.
-
Get All Users (Admin) (
getAllUserfunction):- Fetch all users from the database.
- Send the list of users as a response.
-
Get Single User (Admin) (
getSingleUserfunction):- Find a user based on the provided user ID.
- Send the user details as a response.
-
Update User Role (Admin) (
updateUserRolefunction):- Update the user's name, email, and role based on the request body.
- Send a success message as a response.
-
Delete User (Admin) (
deleteUserfunction):- Find a user based on the provided user ID.
- Remove the user from the database.
- Send a success message as a response.
-
Importing required modules and files:
catchAsyncError: Middleware function to catch asynchronous errors.Variety: The variety model for interacting with the database.ErrorHandler: A custom error handling utility.
-
Add Varieties (
addVarietiesfunction):- Create new varieties in the database using the data from the request body.
- Send a success response with the created varieties.
-
Get Variety Details (
getVaritiesDetailsfunction):- Find a variety based on the provided variety ID.
- Send the variety details as a response.
-
Update Varieties (Admin) (
updateVarietiesfunction):- Find a variety based on the provided variety ID.
- Update the variety with the data from the request body.
- Send a success response with the updated variety.
-
Delete Varieties (Admin) (
deleteVarietiesfunction):- Find a variety based on the provided variety ID.
- Remove the variety from the database.
- Send a success response.
-
Importing required modules:
mongoose: The Mongoose library for MongoDB interactions.
-
Configuring Mongoose settings:
mongoose.set("strictQuery", false): This line sets thestrictQueryoption tofalse, which allows Mongoose to execute queries even if they contain fields not defined in the schema.
-
Connect to the MongoDB database:
- The
connectDatabasefunction establishes a connection to the MongoDB database using themongoose.connectmethod. - It uses the
process.env.MONGO_URLenvironment variable to specify the URL of the MongoDB database. - The
useNewUrlParseranduseUnifiedTopologyoptions are passed to themongoose.connectmethod for proper configuration. - If the connection is successful, the message "connected..." is logged to the console.
- The
-
Exporting the
connectDatabasefunction to be used by other parts of the application.
-
Importing required modules:
catchAsyncErrors: A middleware function that wraps asynchronous route handlers and catches any errors that occur.ErrorHandler: A custom error handling utility.jwt: The JSON Web Token library for working with tokens.User: The User model representing the user collection in the database.
-
Middleware function for user authentication (
isAuthenticatedUser):- This middleware function is responsible for authenticating the user based on the provided token.
- It expects the token to be stored in the
tokenfield of the request cookies. - If no token is found, it returns an authentication error.
- If a token is found, it verifies the token using the
jwt.verifymethod and theprocess.env.JWT_SECRETenvironment variable. - If the token is valid, it retrieves the user information from the database based on the decoded token data and attaches it to the
req.userobject. - Finally, it calls the
nextfunction to pass control to the next middleware or route handler.
-
Middleware function for role authorization (
authorizeRoles):- This middleware function takes a variable number of role parameters (
...roles) that are allowed to access a specific resource. - It returns another middleware function that will be used as a route handler.
- The returned middleware function checks if the user's role (
req.user.role) is included in the provided roles. - If the user's role is not included, it returns a forbidden error (
403). - If the user's role is allowed, it calls the
nextfunction to pass control to the next middleware or route handler.
- This middleware function takes a variable number of role parameters (
This higher-order function is useful for handling asynchronous operations in route handlers and ensuring any errors are properly caught and forwarded to the error-handling middleware.
- The higher-order function takes
theFuncas an argument. - It returns another middleware function with the signature
(req, res, next). - Inside the returned middleware function,
theFunc(req, res, next)is called and executed. - The return value of
theFuncis wrapped in aPromise.resolve()call to ensure it resolves to a promise. - The promise is then chained with
.catch(next)to handle any errors that occur during the execution oftheFunc. - If an error occurs, the
nextfunction is called with the error as an argument, passing control to the next error-handling middleware.
This error handling middleware allows you to handle specific types of errors and provide custom error messages and status codes in your Express application.
- The middleware function takes four parameters:
err,req,res, andnext. - It checks if the
errobject has astatusCodeproperty. If not, it sets it to500(Internal server error). - It checks if the
errobject has amessageproperty. If not, it sets it to"Internal server error". - The middleware then checks for specific types of errors and modifies the
errobject accordingly:- If the error is a MongoDB CastError, it creates a new
ErrorHandlerwith a custom message and a400status code. - If the error is a Mongoose duplicate key error (code 11000), it creates a new
ErrorHandlerwith a custom message and a400status code. - If the error is a JsonWebTokenError, it creates a new
ErrorHandlerwith a custom message and a400status code. - If the error is a TokenExpiredError, it creates a new
ErrorHandlerwith a custom message and a400status code.
- If the error is a MongoDB CastError, it creates a new
- Finally, the middleware sends a JSON response with the appropriate status code and error message.
/register- POST request to register a new user. Calls theregisterUsercontroller function./login- POST request to log in a user. Calls theloginUsercontroller function./password/forgot- POST request to initiate the password reset process. Calls theforgotPasswordcontroller function./password/reset/:token- PUT request to reset the password using a reset token. Calls theresetPasswordcontroller function./me- GET request to fetch the current user's details. Requires authentication (isAuthenticatedUsermiddleware). Calls thegetUserDetailscontroller function./password/update- PUT request to update the user's password. Requires authentication. Calls theupdatePasswordcontroller function./me/update- PUT request to update the user's profile. Requires authentication. Calls theupdateProfilecontroller function./admin/users- GET request to fetch all users (admin access required). Requires authentication and authorization with the role "admin". Calls thegetAllUsercontroller function./admin/user/:id- GET, PUT, DELETE requests for a single user (admin access required). Requires authentication and authorization with the role "admin". Calls thegetSingleUser,updateUserRole, anddeleteUsercontroller functions respectively./logout- GET request to log out the user. Calls thelogoutcontroller function.
POST /varieties/create- Creates a new variety. Requires authentication and authorization with the role "admin" (isAuthenticatedUserandauthorizeRolesmiddlewares). Calls theaddVarietiescontroller function.GET /varieties/:id- Retrieves details of a single variety by its ID. Calls thegetVaritiesDetailscontroller function.PUT /admin/varieties/:id- Updates a variety by its ID. Requires authentication and authorization with the role "admin". Calls theupdateVarietiescontroller function.DELETE /admin/varieties/:id- Deletes a variety by its ID. Requires authentication and authorization with the role "admin". Calls thedeleteVarietiescontroller function.
POST /order/new- Creates a new order. Requires authentication (isAuthenticatedUsermiddleware). Calls thenewOrdercontroller function.GET /order/:id- Retrieves details of a single order by its ID. Requires authentication (isAuthenticatedUsermiddleware). Calls thegetSingleOrdercontroller function.GET /myorders- Retrieves all orders placed by the currently authenticated user. Requires authentication (isAuthenticatedUsermiddleware). Calls themyOrderscontroller function.GET /admin/orders- Retrieves all orders. Requires authentication and authorization with the role "admin" (isAuthenticatedUserandauthorizeRolesmiddlewares). Calls thegetAllOrderscontroller function.PUT /admin/order/:id- Updates the status of an order by its ID. Requires authentication and authorization with the role "admin". Calls theupdateOrderStatuscontroller function.DELETE /admin/order/:id- Deletes an order by its ID. Requires authentication and authorization with the role "admin". Calls thedeleteOrdercontroller function.
POST /product/create- Creates a new product. Requires authentication and authorization with the role "admin" (isAuthenticatedUserandauthorizeRolesmiddlewares). Calls thecreateProductcontroller function.GET /products- Retrieves all products. Does not require authentication. Calls theshowAllProductscontroller function.GET /product/:id- Retrieves details of a single product by its ID. Does not require authentication. Calls thegetProductDetailscontroller function.PUT /admin/product/:id- Updates a product by its ID. Requires authentication and authorization with the role "admin". Calls theupdateProductcontroller function.DELETE /admin/product/:id- Deletes a product by its ID. Requires authentication and authorization with the role "admin". Calls thedeleteProductcontroller function.PUT /review- Creates a new review for a product. Requires authentication. Calls thecreateProductReviewcontroller function.GET /review- Retrieves all reviews for a product. Does not require authentication. Calls thegetProductReviewscontroller function.DELETE /review- Deletes a review. Requires authentication. Calls thedeleteReviewcontroller function.GET /admin/products- Retrieves all products for the admin. Requires authentication and authorization with the role "admin". Calls thegetAdminProductscontroller function.
-
The
ErrorHandlerclass is defined, extending theErrorclass. -
The constructor function is defined with two parameters:
messageandstatusCode. -
Inside the constructor, the
super()method is called with themessageparameter to set the error message. -
The
statusCodeparameter is assigned to thestatusCodeproperty of theErrorHandlerinstance. -
The
Error.captureStackTrace()method is called to capture the stack trace of the error. -
Finally, the
ErrorHandlerclass is exported to be used in other modules. -
The
sendTokenfunction is defined with three parameters:user,statusCode, andres(the response object). -
Inside the function, the
getJWTToken()method is called on theuserobject to generate a JWT token. -
Options for the cookie are defined, including the expiration date based on the value of
COOKIE_EXPIRESfrom the environment variables. -
The
res.cookie()method is called to set thetokencookie with the generated JWT token and the defined options. -
Finally, a JSON response is sent back with the specified
statusCode, along with theuserobject and the generatedtoken. -
The
sendEmailfunction is defined with a single parameteroptions, which is an object containing the email details such asemail,subject,message, andhtml(optional). -
Inside the function, a transporter is created using
nodemailer.createTransport(). The transporter configuration includes the SMTP host, port, service, and authentication credentials (username and password) retrieved from environment variables. -
The
mailOptionsobject is created, which contains the email details such as the sender, recipient, subject, text body, and HTML body. -
The
transporter.sendMail()method is called with themailOptionsto send the email asynchronously.
- The Express application is created with
const app = express(). - Middleware and dependencies are imported:
errorMiddlewareis imported from'./middleware/error'. This middleware handles error responses.cookieParseris imported from'cookie-parser'. It parses cookie headers and populatesreq.cookieswith the parsed cookies.dotenvis imported to load environment variables from the "backend/config/config.env" file.corsis imported to enable Cross-Origin Resource Sharing.
- Configuration is loaded with
dotenv.config({path:"backend/config/config.env"}), which reads environment variables from the specified file. - Middleware is added to the application:
cors()middleware is used to enable CORS.cookieParser()middleware is added to parse cookies.express.json()middleware is added to parse JSON request bodies.
- Route files are imported:
userRoutes,animalTypeRoutes,treatmentTypeRoute,productsRoute,dailyEssentialRoutes,medicalCareRoute,orderRoutes, andvarietyRoutesare imported.
- Routes are mounted to the application using
app.use():- All routes from each route file are mounted under the "/api/v1" path.
- A wildcard route is added to handle any unmatched routes. It responds with a 404 status and an error message.
- The
errorMiddlewareis added as the last middleware to handle errors in the application. - The application is exported as
app.
- The dotenv.config() function is called to load environment variables from the "backend/config/config.env" file.
- The
connectDatabasefunction is called to establish a connection with the database. - The
process.on("uncaughtException", ...)event handler is set up to handle uncaught exceptions. If an uncaught exception occurs, the error message is logged, and the server is shut down by callingprocess.exit(1). - The
process.env.PORTvariable is used to determine the port on which the server will listen. - The server is started by calling
app.listen(port, ...), and a message is logged to indicate that the server is running. - The
process.on("unhandledRejection", ...)event handler is set up to handle unhandled promise rejections. If an unhandled promise rejection occurs, the error message is logged, and the server is shut down by callingserver.close()and thenprocess.exit(1).
there are some changes you have to do in code during development time to run it locally
- app.js (development)
app.use(cors({
origin: 'http://localhost:3000',
credentials: true,
methods: ['GET','PUT','POST','OPTIONS']
}));
- app.js (production) -> as in azure portal cors is enabled and frontend url is added.
app.use(cors());
- jwtToken.js (development) ->
httpOnly: true
const sendToken = (user,statusCode, res) =>{
const token = user.getJWTToken();
//options for cookie
const options = {
expires: new Date(
Date.now() + process.env.COOKIE_EXPIRES * 24 * 60 * 60 *1000
),
httpOnly: true,
};
res.status(statusCode).cookie("token", token,options).json({
success:true,
user,
token,
})
}
- jwtToken.js (production) -> comment httpOnly: true , and add
-
sameSite: 'none'
-
const sendToken = (user,statusCode, res) =>{
const token = user.getJWTToken();
//options for cookie
const options = {
expires: new Date(
Date.now() + process.env.COOKIE_EXPIRES * 24 * 60 * 60 *1000
),
//for dev hhtpOnly:true
// httpOnly: true,
secure: true,
sameSite: 'none'
};
res.status(statusCode).cookie("token", token,options).json({
success:true,
user,
token,
})
}
- controllers/userController.js (development)
In
logoutfunction
exports.logout = catchAsyncErrors(async(req,res,nex)=>{
res.cookie("token",null,{
expires: new Date(Date.now()),
httpOnly:true
})
res.status(200).json({
success:true,
message:" Logged Out",
})
})
- controllers/userController.js (development)
In
logoutfunction
exports.logout = catchAsyncErrors(async(req,res,nex)=>{
res.cookie("token",null,{
expires: new Date(Date.now()),
//for dev hhtpOnly:true
// httpOnly: true,
secure: true,
sameSite: 'none'
})
res.status(200).json({
success:true,
message:" Logged Out",
})
})