From 3056fbd2b3389ea22d457a91606747d0ba14c2c7 Mon Sep 17 00:00:00 2001 From: ROSHAN GARG Date: Mon, 9 Sep 2024 13:13:43 +0530 Subject: [PATCH 1/2] updated the pdOrderControllers --- resources/PD_Orders/pdOrderController.js | 7 +++++++ resources/PD_Orders/pdOrderRoute.js | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/resources/PD_Orders/pdOrderController.js b/resources/PD_Orders/pdOrderController.js index 26dacfc..335d0d7 100644 --- a/resources/PD_Orders/pdOrderController.js +++ b/resources/PD_Orders/pdOrderController.js @@ -702,7 +702,14 @@ const formatDate = (date) => { export const getOrderCounts = async (req, res) => { try { + // console.log(req.user._id,""); + const userId = req.user._id; const statusCounts = await PdOrder.aggregate([ + { + $match: { + addedBy: userId, // Only match orders added by the current user + }, + }, { $group: { _id: "$status", // Group by status diff --git a/resources/PD_Orders/pdOrderRoute.js b/resources/PD_Orders/pdOrderRoute.js index 647dfa4..513383b 100644 --- a/resources/PD_Orders/pdOrderRoute.js +++ b/resources/PD_Orders/pdOrderRoute.js @@ -50,6 +50,6 @@ router router .route("/change/status/:id") .patch(isAuthenticatedUser, authorizeRoles("admin"), updateOrderStatusById); -router.route("/get-counts-pdOrders").get(getOrderCounts); +router.route("/get-counts-pdOrders").get(isAuthenticatedUser, getOrderCounts); export default router; From aebdca98cf3c331ffa50d3de03fd28f713e4abd6 Mon Sep 17 00:00:00 2001 From: ROSHAN GARG Date: Mon, 9 Sep 2024 16:49:29 +0530 Subject: [PATCH 2/2] added the auth of the RD --- .env | 2 +- app.js | 5 +- middlewares/rdAuth.js | 38 +++ resources/KYC/KycController.js | 10 +- .../RetailDistributerRoutes.js | 28 +++ .../RetailDistributorController.js | 218 ++++++++++++++++++ .../RetailDistributorModel.js | 9 +- 7 files changed, 301 insertions(+), 9 deletions(-) create mode 100644 middlewares/rdAuth.js create mode 100644 resources/RetailDistributor/RetailDistributerRoutes.js diff --git a/.env b/.env index 0d4aecf..fdbc82a 100644 --- a/.env +++ b/.env @@ -32,7 +32,7 @@ RAZERPAY_KEY_ID="rzp_test_2rg1Bq3Ki8xw9e" RAZERPAY_SECRET_KEY="WFhHbXL7AlLIuull9kKjYiNA" FRONTEND_URL="https://smellika.com" -PD_APP_URL="https://principal-distributer-cheminova.netlify.app" +PD_APP_URL="https://pd.cnapp.co.in/#/login" SEND_EMAIL_FROM="cheminova2004@gmail.com" diff --git a/app.js b/app.js index 1949d2f..429b1ba 100644 --- a/app.js +++ b/app.js @@ -159,6 +159,8 @@ import shopImageRoute from "./resources/ShopPageImage/ShopPageImageRoute.js"; import ContentRoute from "./resources/Content/ContentRoutes.js"; import UserAddressRoute from "./resources/userAddress/useAddressRoute.js"; import CurrencyRoute from "./resources/Currency/CurrencyRoute.js"; +// RD Routes +import RDRoute from './resources/RetailDistributor/RetailDistributerRoutes.js' //business_Type // import Business_TypeRoute from "./resources/setting/Business_Type/Business_routes.js"; @@ -272,7 +274,8 @@ app.use("/api/inventory", InventoryRoute); app.use("/api/sales", SalesRoute); //Task app.use("/api/task", TaskRoute); - +// RD Rotuts +app.use("/api",RDRoute) //config specialty // app.use("/api/config/specialty", SpecialtiesRouter); //specialties diff --git a/middlewares/rdAuth.js b/middlewares/rdAuth.js new file mode 100644 index 0000000..c51451c --- /dev/null +++ b/middlewares/rdAuth.js @@ -0,0 +1,38 @@ +import jwt from "jsonwebtoken"; +import RetailDistributor from "../resources/RetailDistributor/RetailDistributorModel.js"; + +// import { Business } from "../resources/Businesses/BusinessModel.js"; + +export const isAuthenticatedRD = async (req, res, next) => { + try { + if (!req.headers.authorization) { + return res.status(400).json({ + success: false, + message: "Login to Access this resource", + }); + } + const getToken = req.headers; + // console.log(getToken); + //remove Bearer from token + const fronttoken = getToken.authorization.slice(7); + + const frontdecoded = jwt.verify(fronttoken, process.env.JWT_SECRET); + if (!frontdecoded) { + return res.status(400).json({ + success: false, + message: "incorrect token", + }); + } + // console.log(frontdecoded); + const fuser = await RetailDistributor.findById(frontdecoded.id); + // console.log(fuser); + req.user = fuser; + + next(); + } catch (error) { + return res.status(400).json({ + success: false, + message: error.message, + }); + } +}; diff --git a/resources/KYC/KycController.js b/resources/KYC/KycController.js index a12cb84..8406c91 100644 --- a/resources/KYC/KycController.js +++ b/resources/KYC/KycController.js @@ -47,7 +47,10 @@ export const createKyc = async (req, res) => { if (!mongoose.Types.ObjectId.isValid(req.user._id)) { return res.status(400).json({ message: "Please login again" }); } - + const isExits = await KYC.find({ email: email }); + if (isExits.length > 0) { + throw new Error("Email already exists"); + } // Upload images to Cloudinary and store only public_id and url const uploadImage = async (image, folder) => { if (!image) return null; @@ -378,7 +381,7 @@ export const getKycById = async (req, res) => { export const updateKycStatus = async (req, res) => { const { status, rejectionReason, user } = req.body; - console.log(status); + const { id } = req.params; // console.log(user, rejectionReason, status); try { @@ -394,7 +397,7 @@ export const updateKycStatus = async (req, res) => { const trade_name = kyc.trade_name; if (status === "approved") { kyc.status = status; - console.log("inside Approved "); + await rejectKYC( kyc.addedBy, "KYC Approved", @@ -407,6 +410,7 @@ export const updateKycStatus = async (req, res) => { added_for: kyc.addedBy, // userType: req.userType, }); + // Generate a secure password for RetailDistributor const password = generatePassword(kyc.name, kyc.email); diff --git a/resources/RetailDistributor/RetailDistributerRoutes.js b/resources/RetailDistributor/RetailDistributerRoutes.js new file mode 100644 index 0000000..5bbad7b --- /dev/null +++ b/resources/RetailDistributor/RetailDistributerRoutes.js @@ -0,0 +1,28 @@ +import express from "express"; +import { + ChangePasswordRD, + forgotPassword, + getmyProfile, + loginRD, + UpdateProfile, +} from "./RetailDistributorController.js"; +import { isAuthenticatedRD } from "../../middlewares/rdAuth.js"; + +const router = express.Router(); + +router.route("/rd-login").post(loginRD); +router.route("/rd-get-me").get(isAuthenticatedRD, getmyProfile); +router.post("/forgot-password", forgotPassword); +router.put( + "/rd-password/update", + isAuthenticatedRD, + + ChangePasswordRD +); +router.patch( + "/rd-profile/update", + isAuthenticatedRD, + + UpdateProfile +); +export default router; diff --git a/resources/RetailDistributor/RetailDistributorController.js b/resources/RetailDistributor/RetailDistributorController.js index e69de29..aa3c66e 100644 --- a/resources/RetailDistributor/RetailDistributorController.js +++ b/resources/RetailDistributor/RetailDistributorController.js @@ -0,0 +1,218 @@ +import RetailDistributor from "./RetailDistributorModel.js"; +import validator from "validator"; +export const loginRD = async (req, res) => { + const { email, password } = req.body; + + try { + if (!email || !password) { + return res.status(400).json({ message: "Please Enter Email & Password" }); + } + + const retailDistributor = await RetailDistributor.findOne({ email }).select( + "+password" + ); + + if (!retailDistributor) { + return res.status(400).json({ message: "Invalid Email or Password" }); + } + + const isPasswordMatched = await retailDistributor.comparePassword(password); + + if (!isPasswordMatched) { + return res.status(400).json({ message: "Invalid Email or Password" }); + } + const token = retailDistributor.getJWTToken(); + + return res.status(200).json({ + success: true, + token, + message: "Login Successfully", + }); + } catch (error) { + return res.status(500).json({ + message: error.message ? error.message : "Something went wrong!", + }); + } +}; + +export const ChangePasswordRD = async (req, res) => { + // Retrieve id from req.params + const { oldPassword, newPassword, confirmPassword } = req.body; + const userId = req.user._id; // Use the ID from the URL or from the authenticated user + // console.log(userId); + if (!oldPassword) { + return res.status(400).json({ message: "Please Enter Old password" }); + } + if (!newPassword) { + return res.status(400).json({ message: "Please Enter New Password " }); + } + if (!confirmPassword) { + return res.status(400).json({ message: "Please Enter Confirm Password" }); + } + try { + const retailDistributor = await RetailDistributor.findById(userId).select( + "+password" + ); + + if (!retailDistributor) { + return res.status(404).json({ message: "Retail Distributer not found" }); + } + + const isPasswordMatched = await retailDistributor.comparePassword( + oldPassword + ); + + if (!isPasswordMatched) { + return res.status(400).json({ message: "Old password is incorrect" }); + } + + if (newPassword !== confirmPassword) { + return res + .status(400) + .json({ message: "New password and confirm Password do not match" }); + } + + retailDistributor.password = newPassword; + await retailDistributor.save(); + + return res + .status(200) + .json({ success: true, message: "Password updated successfully" }); + } catch (error) { + console.error("Error updating password:", error); + return res.status(500).json({ + message: error.message ? error.message : "Server error!", + }); + } +}; + +export const forgotPassword = async (req, res) => { + try { + // Check if email is provided + const { email } = req.body; + if (!email) { + return res.status(400).json({ message: "Please Enter Email!" }); + } + + // Find the Retail Distributor by email + const retailDistributor = await RetailDistributor.findOne({ email }); + if (!retailDistributor) { + return res.status(404).json({ message: "Retail Distributor not found" }); + } + + // Generate a random password + const newPassword = password.randomPassword({ + length: 12, + characters: [ + { characters: password.upper, exactly: 1 }, // At least 1 uppercase letter + { characters: password.symbols, exactly: 1 }, // At least 1 symbol + password.lower, // Lowercase letters + password.digits, // Digits + ], + }); + + // Update the retail distributor's password + retailDistributor.password = newPassword; + await retailDistributor.save(); // The pre-save hook in your schema will handle password hashing + + // Send an email to the retail distributor with the new password + await sendEmail({ + to: retailDistributor.email, + from: process.env.SEND_EMAIL_FROM, + subject: `Cheminova Password Recovery`, + html: `Your new password is: ${newPassword}

If you did not request this, please ignore this email.`, + }); + + // Respond with success message + return res.status(200).json({ + success: true, + message: `Email sent to ${retailDistributor.email} successfully`, + }); + } catch (error) { + console.error("Error during password reset:", error); + return res.status(500).json({ + message: error.message || "Something went wrong!", + }); + } +}; + +export const UpdateProfile = async (req, res) => { + const { name, email } = req.body; + + const userId = req.user._id; // Use the ID from params or authenticated user + + // Validate email if provided + if (email && !validator.isEmail(email)) { + return res.status(400).json({ message: "Invalid email address" }); + } + + try { + // Find the RetailDistributor by user ID + const retailDistributor = await RetailDistributor.findById(userId); + + if (!retailDistributor) { + return res.status(404).json({ message: "Retail Distributor not found" }); + } + + // Assuming you have an 'isVerified' field in your RetailDistributor schema + if (!retailDistributor.isVerified) { + return res + .status(400) + .json({ message: "Retail Distributor not verified" }); + } + + // Check if email is being changed and if it's already in use + if (email && email !== retailDistributor.email) { + const emailExists = await RetailDistributor.findOne({ email }); + if (emailExists && emailExists._id.toString() !== userId) { + return res.status(400).json({ + message: + "This Email ID is already in use by another Retail Distributor", + }); + } + retailDistributor.email = email; + } + + // Update name if provided + if (name) { + retailDistributor.name = name; + } + + // Save the updated RetailDistributor + await retailDistributor.save(); + + return res.status(200).json({ + retailDistributor, + message: "Profile updated successfully", + }); + } catch (error) { + return res.status(500).json({ + message: error.message || "Server error!", + }); + } +}; + +export const getmyProfile = async (req, res) => { + try { + // Fetch the profile data using the authenticated user's ID + const myData = await RetailDistributor.findById(req.user?._id); + + if (myData) { + return res.status(200).json({ + success: true, + message: "Profile fetched successfully!", + myData, + }); + } else { + return res.status(404).json({ + success: false, + message: "Retail Distributor not found", + }); + } + } catch (error) { + return res.status(500).json({ + success: false, + message: error.message || "Something went wrong!", + }); + } +}; diff --git a/resources/RetailDistributor/RetailDistributorModel.js b/resources/RetailDistributor/RetailDistributorModel.js index a44164f..96f5452 100644 --- a/resources/RetailDistributor/RetailDistributorModel.js +++ b/resources/RetailDistributor/RetailDistributorModel.js @@ -68,9 +68,8 @@ const RetailDistributorSchema = new mongoose.Schema( resetPasswordExpire: Date, fcm_token: { type: String, - unique: true, + default: null, }, - }, { timestamps: true } ); @@ -102,7 +101,9 @@ RetailDistributorSchema.pre("save", function (next) { // JWT TOKEN RetailDistributorSchema.methods.getJWTToken = function () { - return jwt.sign({ id: this._id }, process.env.JWT_SECRET); + return jwt.sign({ id: this._id }, process.env.JWT_SECRET, { + expiresIn: "1d", // Token will expire in 1 day + }); }; // Compare Password @@ -128,4 +129,4 @@ const RetailDistributor = mongoose.model( "RetailDistributor", RetailDistributorSchema ); -export default RetailDistributor; \ No newline at end of file +export default RetailDistributor;