- 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 install
This will install all the dependencies listed in thepackage.json
file. -
Configure environment variables To configure environment variables when the
.env
file 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
config
and inside it create your.env
file. - Define environment variables
Inside the
.env
file, 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>
[email protected]
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
shippingInfo
field. -
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
animalName
already exists in the database (case-insensitive). If it exists, it returns an error message. Otherwise, it creates a new animal category using theAnimal
model 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
Animal
model. 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_id
parameter) 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_id
parameter) 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
essentialName
already exists in the database (case-insensitive). If it exists, it returns an error message. Otherwise, it creates a new essential category using theEssential
model 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
Essential
model. 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_id
parameter) 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_id
parameter) 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
medicalCareName
already exists in the database (case-insensitive). If it exists, it returns an error message. Otherwise, it creates a new medical care category using theMedical
model 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
Medical
model. 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_id
parameter) 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_id
parameter) 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
TreatmentTypeName
already exists in the database (case-insensitive). If it exists, it returns an error message. Otherwise, it creates a new treatment category using theTreatment
model 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
Treatment
model. 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_id
parameter) 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_id
parameter) 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.
-
newOrder
function: 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.create
method, 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
sendEmail
function. - Finally, it sends a JSON response with the created order.
- It extracts the required information from the request body, such as
-
getSingleOrder
function: This function retrieves a single order by its ID.- It uses the
Order.findById
method to find the order with the specified ID and populates theuser
field with the corresponding user'sname
andemail
. - If the order is not found, it returns an error.
- Otherwise, it sends a JSON response with the retrieved order.
- It uses the
-
myOrders
function: This function retrieves all orders for the logged-in user.- It uses the
Order.find
method to find orders where theuser
field matches the ID of the logged-in user. - It sends a JSON response with the retrieved orders.
- It uses the
-
getAllOrders
function: This function retrieves all orders (for admin use).- It uses the
Order.find
method to find all orders. - It calculates the
totalAmount
by summing up thetotalPrice
of each order. - It sends a JSON response with the total amount and the retrieved orders.
- It uses the
-
updateOrderStatus
function: This function updates the status of an order (for admin use).- It uses the
Order.findById
method 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
updateStock
function. - It updates the order status based on the
status
provided in the request body and sets thedeliveredAt
field if the status is "Delivered". - It saves the updated order and sends a JSON response.
- It uses the
-
updateStock
function: This function updates the stock of a product.- It takes the product ID and quantity as parameters.
- It retrieves the product using the
Product.findById
method. - It subtracts the quantity from the product's
Stock
property and saves the product.
-
deleteOrder
function: This function deletes an order (for admin use).- It uses the
Order.findByIdAndRemove
method 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 theuser
field to the current user's ID, creates a new product using theProduct
model, and returns the created product as a JSON response. If an error occurs, it calls thenext
function 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 theProduct
model, and returns the product details as a JSON response. If the product is not found, it calls thenext
function 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.findByIdAndUpdate
method. It returns the updated product as a JSON response. If the product is not found, it calls thenext
function with an error. -
deleteProduct
: This function deletes a product. It finds the product using the provided ID and removes it using theProduct.findByIdAndRemove
method. It returns a JSON response indicating the success of the deletion. If the product is not found, it calls thenext
function 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.find
query to retrieve the matching products. The results are paginated using thepage
andpageSize
parameters. 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 thenext
function 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
, andreviews
fields 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 theProduct
model, and returns the reviews as a JSON response. If the product is not found, it calls thenext
function 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'sreviews
array, 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.find
method 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 (
registerUser
function):- 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 (
loginUser
function):- 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 (
logout
function):- Clear the JWT token cookie in the response.
- Send a success message.
-
Forgot Password (
forgotPassword
function):- 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 (
resetPassword
function):- 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 (
getUserDetails
function):- Find the user details based on the user ID from the JWT token.
- Send the user details as a response.
-
Update Password (
updatePassword
function):- 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 (
updateProfile
function):- 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) (
getAllUser
function):- Fetch all users from the database.
- Send the list of users as a response.
-
Get Single User (Admin) (
getSingleUser
function):- Find a user based on the provided user ID.
- Send the user details as a response.
-
Update User Role (Admin) (
updateUserRole
function):- Update the user's name, email, and role based on the request body.
- Send a success message as a response.
-
Delete User (Admin) (
deleteUser
function):- 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 (
addVarieties
function):- Create new varieties in the database using the data from the request body.
- Send a success response with the created varieties.
-
Get Variety Details (
getVaritiesDetails
function):- Find a variety based on the provided variety ID.
- Send the variety details as a response.
-
Update Varieties (Admin) (
updateVarieties
function):- 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) (
deleteVarieties
function):- 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 thestrictQuery
option tofalse
, which allows Mongoose to execute queries even if they contain fields not defined in the schema.
-
Connect to the MongoDB database:
- The
connectDatabase
function establishes a connection to the MongoDB database using themongoose.connect
method. - It uses the
process.env.MONGO_URL
environment variable to specify the URL of the MongoDB database. - The
useNewUrlParser
anduseUnifiedTopology
options are passed to themongoose.connect
method for proper configuration. - If the connection is successful, the message "connected..." is logged to the console.
- The
-
Exporting the
connectDatabase
function 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
token
field 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.verify
method and theprocess.env.JWT_SECRET
environment 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.user
object. - Finally, it calls the
next
function 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
next
function 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
theFunc
as 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
theFunc
is 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
next
function 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
err
object has astatusCode
property. If not, it sets it to500
(Internal server error). - It checks if the
err
object has amessage
property. If not, it sets it to"Internal server error"
. - The middleware then checks for specific types of errors and modifies the
err
object accordingly:- If the error is a MongoDB CastError, it creates a new
ErrorHandler
with a custom message and a400
status code. - If the error is a Mongoose duplicate key error (code 11000), it creates a new
ErrorHandler
with a custom message and a400
status code. - If the error is a JsonWebTokenError, it creates a new
ErrorHandler
with a custom message and a400
status code. - If the error is a TokenExpiredError, it creates a new
ErrorHandler
with a custom message and a400
status 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 theregisterUser
controller function./login
- POST request to log in a user. Calls theloginUser
controller function./password/forgot
- POST request to initiate the password reset process. Calls theforgotPassword
controller function./password/reset/:token
- PUT request to reset the password using a reset token. Calls theresetPassword
controller function./me
- GET request to fetch the current user's details. Requires authentication (isAuthenticatedUser
middleware). Calls thegetUserDetails
controller function./password/update
- PUT request to update the user's password. Requires authentication. Calls theupdatePassword
controller function./me/update
- PUT request to update the user's profile. Requires authentication. Calls theupdateProfile
controller function./admin/users
- GET request to fetch all users (admin access required). Requires authentication and authorization with the role "admin". Calls thegetAllUser
controller 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
, anddeleteUser
controller functions respectively./logout
- GET request to log out the user. Calls thelogout
controller function.
POST /varieties/create
- Creates a new variety. Requires authentication and authorization with the role "admin" (isAuthenticatedUser
andauthorizeRoles
middlewares). Calls theaddVarieties
controller function.GET /varieties/:id
- Retrieves details of a single variety by its ID. Calls thegetVaritiesDetails
controller function.PUT /admin/varieties/:id
- Updates a variety by its ID. Requires authentication and authorization with the role "admin". Calls theupdateVarieties
controller function.DELETE /admin/varieties/:id
- Deletes a variety by its ID. Requires authentication and authorization with the role "admin". Calls thedeleteVarieties
controller function.
POST /order/new
- Creates a new order. Requires authentication (isAuthenticatedUser
middleware). Calls thenewOrder
controller function.GET /order/:id
- Retrieves details of a single order by its ID. Requires authentication (isAuthenticatedUser
middleware). Calls thegetSingleOrder
controller function.GET /myorders
- Retrieves all orders placed by the currently authenticated user. Requires authentication (isAuthenticatedUser
middleware). Calls themyOrders
controller function.GET /admin/orders
- Retrieves all orders. Requires authentication and authorization with the role "admin" (isAuthenticatedUser
andauthorizeRoles
middlewares). Calls thegetAllOrders
controller function.PUT /admin/order/:id
- Updates the status of an order by its ID. Requires authentication and authorization with the role "admin". Calls theupdateOrderStatus
controller function.DELETE /admin/order/:id
- Deletes an order by its ID. Requires authentication and authorization with the role "admin". Calls thedeleteOrder
controller function.
POST /product/create
- Creates a new product. Requires authentication and authorization with the role "admin" (isAuthenticatedUser
andauthorizeRoles
middlewares). Calls thecreateProduct
controller function.GET /products
- Retrieves all products. Does not require authentication. Calls theshowAllProducts
controller function.GET /product/:id
- Retrieves details of a single product by its ID. Does not require authentication. Calls thegetProductDetails
controller function.PUT /admin/product/:id
- Updates a product by its ID. Requires authentication and authorization with the role "admin". Calls theupdateProduct
controller function.DELETE /admin/product/:id
- Deletes a product by its ID. Requires authentication and authorization with the role "admin". Calls thedeleteProduct
controller function.PUT /review
- Creates a new review for a product. Requires authentication. Calls thecreateProductReview
controller function.GET /review
- Retrieves all reviews for a product. Does not require authentication. Calls thegetProductReviews
controller function.DELETE /review
- Deletes a review. Requires authentication. Calls thedeleteReview
controller function.GET /admin/products
- Retrieves all products for the admin. Requires authentication and authorization with the role "admin". Calls thegetAdminProducts
controller function.
-
The
ErrorHandler
class is defined, extending theError
class. -
The constructor function is defined with two parameters:
message
andstatusCode
. -
Inside the constructor, the
super()
method is called with themessage
parameter to set the error message. -
The
statusCode
parameter is assigned to thestatusCode
property of theErrorHandler
instance. -
The
Error.captureStackTrace()
method is called to capture the stack trace of the error. -
Finally, the
ErrorHandler
class is exported to be used in other modules. -
The
sendToken
function is defined with three parameters:user
,statusCode
, andres
(the response object). -
Inside the function, the
getJWTToken()
method is called on theuser
object to generate a JWT token. -
Options for the cookie are defined, including the expiration date based on the value of
COOKIE_EXPIRES
from the environment variables. -
The
res.cookie()
method is called to set thetoken
cookie with the generated JWT token and the defined options. -
Finally, a JSON response is sent back with the specified
statusCode
, along with theuser
object and the generatedtoken
. -
The
sendEmail
function 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
mailOptions
object 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 themailOptions
to send the email asynchronously.
- The Express application is created with
const app = express()
. - Middleware and dependencies are imported:
errorMiddleware
is imported from'./middleware/error'
. This middleware handles error responses.cookieParser
is imported from'cookie-parser'
. It parses cookie headers and populatesreq.cookies
with the parsed cookies.dotenv
is imported to load environment variables from the "backend/config/config.env" file.cors
is 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
, andvarietyRoutes
are 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
errorMiddleware
is 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
connectDatabase
function 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.PORT
variable 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
logout
function
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
logout
function
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",
})
})