From 3e95dc3b2a6bc5848f231ab1dc37aaead1b51f12 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Tue, 30 Jul 2024 11:07:19 +0530 Subject: [PATCH] Territory manager details --- app.js | 6 +- middlewares/TerritoryManagerAuth.js | 44 ++ resources/Attendance/AttandanceRoute.js | 6 +- resources/Attendance/AttendanceController.js | 3 +- resources/Leaves/LeaveRoute.js | 6 +- .../SalesCoOrdinatorController.js | 44 +- .../SalesCoOrdinatorRoute.js | 9 +- .../TerritoryManagerController.js | 590 ++++++++++++++++++ .../TerritoryManagerModel.js | 100 +++ .../TerritoryManagerRoute.js | 100 +++ 10 files changed, 875 insertions(+), 33 deletions(-) create mode 100644 middlewares/TerritoryManagerAuth.js create mode 100644 resources/TerritoryManagers/TerritoryManagerController.js create mode 100644 resources/TerritoryManagers/TerritoryManagerModel.js create mode 100644 resources/TerritoryManagers/TerritoryManagerRoute.js diff --git a/app.js b/app.js index 9cc6e6e..7941c23 100644 --- a/app.js +++ b/app.js @@ -138,7 +138,8 @@ import LanguageRoute from "./resources/setting/Language/language_routes.js"; import PurposeRoute from "./resources/setting/Purpose/Purpose_routes.js"; //SalesCoOrdinator Routes import SalesCoOrdinatorRoute from "./resources/SalesCoOrdinators/SalesCoOrdinatorRoute.js"; - +//TerritoryManager Routes +import TerritoryManagerRoute from "./resources/TerritoryManagers/TerritoryManagerRoute.js"; // category Route import categoryRoute from "./resources/Category/categoryRoutes.js"; import RegistrationImageRoute from "./resources/RegistrationImage/RegistrationImageRoute.js"; @@ -194,7 +195,8 @@ app.use("/api/user-address", UserAddressRoute); app.use("/api/shipping/address", ShippingAddressRoute); //SalesCoOrdinator Routes app.use("/api/salescoordinator", SalesCoOrdinatorRoute); - +//TerritoryManager Routes +app.use("/api/territorymanager", TerritoryManagerRoute); //Order app.use("/api/order", orderRoute); //Departure diff --git a/middlewares/TerritoryManagerAuth.js b/middlewares/TerritoryManagerAuth.js new file mode 100644 index 0000000..ab6771e --- /dev/null +++ b/middlewares/TerritoryManagerAuth.js @@ -0,0 +1,44 @@ +import jwt from "jsonwebtoken"; +import TerritoryManager from "../resources/TerritoryManagers/TerritoryManagerModel.js"; + +export const isAuthenticatedTerritoryManager = async (req, res, next) => { + try { + if (!req.headers.authorization) { + return res.status(401).json({ + success: false, + message: "Please login to access this resource", + }); + } + const getToken = req.headers.authorization; + const token = getToken.slice(7); + + const decoded = jwt.verify(token, process.env.JWT_SECRET); + if (!decoded) { + return res.status(400).json({ + success: false, + message: "Incorrect token", + }); + } + const territorymanager = await TerritoryManager.findById(decoded.id); + if (territorymanager) { + req.user = territorymanager; + req.userType = 'TerritoryManager'; + return next(); + } else { + return res.status(401).json({ + success: false, + message: "Unauthorized", + }); + } + } catch (error) { + if (error.name === "TokenExpiredError") { + return res.status(401).json({ message: "Token has expired." }); + } else if (error.name === "JsonWebTokenError") { + return res.status(401).json({ message: "Invalid token." }); + } else { + return res.status(500).json({ + message: "An internal error occurred while verifying the token.", + }); + } + } +}; diff --git a/resources/Attendance/AttandanceRoute.js b/resources/Attendance/AttandanceRoute.js index e074d26..5c3cddc 100644 --- a/resources/Attendance/AttandanceRoute.js +++ b/resources/Attendance/AttandanceRoute.js @@ -6,7 +6,7 @@ import { AdmingetAttendanceByUser, } from "./AttendanceController.js"; import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js"; -// import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js"; +import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js"; import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js"; const router = express.Router(); @@ -31,7 +31,7 @@ router.post( // Route to mark attendance for Territory Managers router.post( "/markattendance/territorymanager", - // isAuthenticatedTerritoryManager, + isAuthenticatedTerritoryManager, markAttendance ); @@ -45,7 +45,7 @@ router.get( // Route to get attendance for the logged-in territory manager router.get( "/attendance/territorymanager", - // isAuthenticatedTerritoryManager, + isAuthenticatedTerritoryManager, getAttendanceByUser ); diff --git a/resources/Attendance/AttendanceController.js b/resources/Attendance/AttendanceController.js index 0f371e0..ed70d56 100644 --- a/resources/Attendance/AttendanceController.js +++ b/resources/Attendance/AttendanceController.js @@ -227,8 +227,7 @@ export const getTodayAttendance = async (req, res) => { date: record.records.date, time: record.records.time, location: record.records.location, - reason: record.records.reason, - leaveType: record.records.leaveType, + notes: record.records.notes, })); // Send response diff --git a/resources/Leaves/LeaveRoute.js b/resources/Leaves/LeaveRoute.js index 9e7ac69..b051b8d 100644 --- a/resources/Leaves/LeaveRoute.js +++ b/resources/Leaves/LeaveRoute.js @@ -6,7 +6,7 @@ import { AdmingetLeaveByUser, } from "./LeaveController.js"; import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js"; -// import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js"; +import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js"; import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js"; const router = express.Router(); @@ -31,7 +31,7 @@ router.post( // Route to mark leave for Territory Managers router.post( "/markleave/territorymanager", - // isAuthenticatedTerritoryManager, + isAuthenticatedTerritoryManager, markLeave ); @@ -45,7 +45,7 @@ router.get( // Route to get leave for the logged-in territory manager router.get( "/leave/territorymanager", - // isAuthenticatedTerritoryManager, + isAuthenticatedTerritoryManager, getLeaveByUser ); diff --git a/resources/SalesCoOrdinators/SalesCoOrdinatorController.js b/resources/SalesCoOrdinators/SalesCoOrdinatorController.js index b300c2d..d99b75d 100644 --- a/resources/SalesCoOrdinators/SalesCoOrdinatorController.js +++ b/resources/SalesCoOrdinators/SalesCoOrdinatorController.js @@ -4,6 +4,7 @@ import SalesCoOrdinator from "./SalesCoOrdinatorModel.js"; import sendEmail, { sendOtp } from "../../Utils/sendEmail.js"; import validator from "validator"; import password from "secure-random-password"; +import catchAsyncErrors from "../../middlewares/catchAsyncErrors.js"; export const register = async (req, res) => { let { name, email, countryCode, mobileNumber } = req.body; @@ -157,7 +158,18 @@ export const loginSalesCoOrdinator = async (req, res) => { }); } }; +// Logout User +export const logout = catchAsyncErrors(async (req, res, next) => { + res.cookie("token", null, { + expires: new Date(Date.now()), + httpOnly: true, + }); + res.status(200).json({ + success: true, + message: "Logged Out", + }); +}); //get All salescoordinator export const getAllSalesCoOrdinator = async (req, res) => { try { @@ -286,13 +298,14 @@ export const forgotPassword = async (req, res) => { //Update mobile Number export const updateMobileNumber = async (req, res) => { const { id } = req.params; + const userId = id || req.user._id; let { newCountryCode, newMobileNumber } = req.body; newCountryCode = newCountryCode?.trim(); newMobileNumber = newMobileNumber?.trim(); const newFullMobileNumber = `${newCountryCode}${newMobileNumber}`; try { - const salescoordinator = await SalesCoOrdinator.findById(id); + const salescoordinator = await SalesCoOrdinator.findById(userId); if (!salescoordinator) { return res.status(400).json({ message: "SalesCoOrdinator not found" }); } @@ -441,14 +454,14 @@ export const deleteSalesCoOrdinator = async (req, res) => { export const UpdateProfile = async (req, res) => { const { name, email } = req.body; const { id } = req.params; - + const userId = id || req.user._id; // Validate email if (!validator.isEmail(email)) { return res.status(400).json({ message: "Invalid email address" }); } try { - const salesCoordinator = await SalesCoOrdinator.findById(id); // Use the ID from params + const salesCoordinator = await SalesCoOrdinator.findById(userId); // Use the ID from params if (!salesCoordinator) { return res.status(404).json({ message: "SalesCoOrdinator not found" }); @@ -461,7 +474,7 @@ export const UpdateProfile = async (req, res) => { // Check if email is being changed and already exists if (email && email !== salesCoordinator.email) { const emailExists = await SalesCoOrdinator.findOne({ email }); - if (emailExists && emailExists._id.toString() !== id) { + if (emailExists && emailExists._id.toString() !== userId) { return res.status(400).json({ message: "This Email ID is already in use by another SalesCoOrdinator", @@ -493,6 +506,7 @@ export const UpdateProfile = async (req, res) => { export const ChangePassword = async (req, res) => { const { id } = req.params; // Retrieve id from req.params const { oldPassword, newPassword, confirmPassword } = req.body; + const userId = id || req.user._id; // Use the ID from the URL or from the authenticated user if (!oldPassword) { return res.status(400).json({ message: "Please Enter Old password" }); @@ -504,34 +518,26 @@ export const ChangePassword = async (req, res) => { return res.status(400).json({ message: "Please Enter Confirm Password" }); } try { - const salescoordinator = await SalesCoOrdinator.findById(id).select( - "+password" - ); + const SalesCoOrdinator = await SalesCoOrdinator.findById(userId).select("+password"); - if (!salescoordinator) { + if (!SalesCoOrdinator) { return res.status(404).json({ message: "SalesCoOrdinator not found" }); } - const isPasswordMatched = await salescoordinator.comparePassword( - oldPassword - ); + const isPasswordMatched = await SalesCoOrdinator.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 does not match" }); + return res.status(400).json({ message: "New password and confirm Password do not match" }); } - salescoordinator.password = newPassword; - await salescoordinator.save(); + SalesCoOrdinator.password = newPassword; + await SalesCoOrdinator.save(); - return res - .status(200) - .json({ success: true, message: "Password updated successfully" }); + return res.status(200).json({ success: true, message: "Password updated successfully" }); } catch (error) { console.error("Error updating password:", error); return res.status(500).json({ diff --git a/resources/SalesCoOrdinators/SalesCoOrdinatorRoute.js b/resources/SalesCoOrdinators/SalesCoOrdinatorRoute.js index a1e54b5..190fadf 100644 --- a/resources/SalesCoOrdinators/SalesCoOrdinatorRoute.js +++ b/resources/SalesCoOrdinators/SalesCoOrdinatorRoute.js @@ -15,6 +15,7 @@ import { getmyProfile, ChangePassword, getOneSalesCoOrdinator, + logout, } from "./SalesCoOrdinatorController.js"; import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js"; import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js"; @@ -22,7 +23,7 @@ import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js"; router.post("/register", register); router.post("/verify-otp", verifyOtp); router.post("/login", loginSalesCoOrdinator); - +router.route("/logout").get(logout); //admin router.get( "/getAll", @@ -46,7 +47,7 @@ router.post( updateMobileNumber ); router.post( - "/update-mobile-number/:id", + "/update-mobile-number", isAuthenticatedSalesCoOrdinator, updateMobileNumber ); @@ -69,7 +70,7 @@ router.patch( UpdateProfile ); router.patch( - "/profile/update/:id", + "/profile/update", isAuthenticatedSalesCoOrdinator, UpdateProfile ); @@ -80,7 +81,7 @@ router.put( authorizeRoles("admin"), ChangePassword ); -router.put("/password/update/:id", isAuthenticatedSalesCoOrdinator, ChangePassword); +router.put("/password/update", isAuthenticatedSalesCoOrdinator, ChangePassword); //delete SalesCoOrdinator router.delete( "/delete/:id", diff --git a/resources/TerritoryManagers/TerritoryManagerController.js b/resources/TerritoryManagers/TerritoryManagerController.js new file mode 100644 index 0000000..45c33e8 --- /dev/null +++ b/resources/TerritoryManagers/TerritoryManagerController.js @@ -0,0 +1,590 @@ +// import hashPassword from '../utils/hashPassword'; +import crypto from "crypto"; +import TerritoryManager from "./TerritoryManagerModel.js"; +import sendEmail, { sendOtp } from "../../Utils/sendEmail.js"; +import validator from "validator"; +import password from "secure-random-password"; +import catchAsyncErrors from "../../middlewares/catchAsyncErrors.js"; + +export const register = async (req, res) => { + let { name, email, countryCode, mobileNumber } = req.body; + countryCode = countryCode?.trim(); + mobileNumber = mobileNumber?.trim(); + const fullMobileNumber = `${countryCode}${mobileNumber}`; + + try { + let territoryManager = await TerritoryManager.findOne({ + mobileNumber: fullMobileNumber, + }); + + if (territoryManager && territoryManager.isVerified) { + return res.status(400).json({ + message: + "TerritoryManager already registered and verified for this mobile number.", + }); + } + // const otp = crypto.randomInt(100000, 1000000).toString(); + const otp = "123456"; + const otpExpires = Date.now() + 1 * 60 * 1000; + + if (territoryManager) { + territoryManager.otp = otp; + territoryManager.otpExpires = otpExpires; + } else { + territoryManager = new TerritoryManager({ + name, + email, + mobileNumber: fullMobileNumber, + otp, + otpExpires, + }); + } + // Generate uniqueId if not already present + if (!territoryManager.uniqueId) { + const currentYear = new Date().getFullYear().toString().slice(-2); + const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase(); + territoryManager.uniqueId = `${currentYear}-${randomChars}`; + } + await territoryManager.save(); + // await sendOtp( + // fullMobileNumber, + // Your Cheminova verification OTP is: ${otp} + // ); + return res.status(200).json({ + message: `OTP sent to your mobile number ${fullMobileNumber} successfully`, + }); + } catch (error) { + res.status(500).json({ + message: error.message ? error.message : "Server error!", + }); + } +}; + +export const verifyOtp = async (req, res) => { + const { fullMobileNumber, otp } = req.body; + + try { + let mobileNmr = fullMobileNumber?.trim(); + const territoryManager = await TerritoryManager.findOne({ + mobileNumber: mobileNmr, + }); + + if (!territoryManager) { + return res.status(400).json({ message: "Invalid mobile number or OTP" }); + } + + if ( + territoryManager.otp !== otp || + territoryManager.otpExpires < Date.now() + ) { + return res.status(400).json({ message: "Invalid or expired OTP" }); + } + const name = territoryManager.name; + const mobile = territoryManager.mobileNumber; + territoryManager.isVerified = true; + territoryManager.otp = undefined; + territoryManager.otpExpires = undefined; + + // Generate a random password + const newPassword = password.randomPassword({ + length: 12, + characters: [ + { characters: password.upper, exactly: 1 }, + { characters: password.symbols, exactly: 1 }, + password.lower, + password.digits, + ], + }); + + // Save the new password (hashed) + territoryManager.password = newPassword; + await territoryManager.save(); + + // Send email with the new password + await sendEmail({ + to: `${territoryManager?.email}`, // Change to your recipient + from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender + subject: `Cheminova Account Created`, + html: `Your Territory Manager Account is created successfully. +
name is: ${name}
+
MobileNumber is: ${mobile}
+
password is: ${newPassword}

If you have not requested this email, please ignore it.`, + }); + + const token = territoryManager.getJWTToken(); + res.status(200).json({ + success: true, + token, + message: "Mobile number verified and new password sent successfully", + }); + } catch (error) { + res.status(500).json({ + message: error.message ? error.message : "Server error!", + }); + } +}; +// Login TerritoryManager +export const loginTerritoryManager = async (req, res) => { + const { email, password } = req.body; + // console.log(email, password); + try { + if (!email || !password) { + return res.status(400).json({ message: "Please Enter Email & Password" }); + } + + const territoryManager = await TerritoryManager.findOne({ email }).select( + "+password" + ); + + if (!territoryManager) { + return res.status(400).json({ message: "Invalid Email or Password" }); + } + + const isPasswordMatched = await territoryManager.comparePassword(password); + + if (!isPasswordMatched) { + return res.status(400).json({ message: "Invalid Email or Password" }); + } + const token = territoryManager.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!", + }); + } +}; +// Logout User +export const logout = catchAsyncErrors(async (req, res, next) => { + res.cookie("token", null, { + expires: new Date(Date.now()), + httpOnly: true, + }); + + res.status(200).json({ + success: true, + message: "Logged Out", + }); +}); +//get All territorymanager +export const getAllTerritoryManager = async (req, res) => { + try { + const PAGE_SIZE = parseInt(req.query?.show || "10"); + const page = parseInt(req.query?.page || "1") - 1; + let filter = {}; + if (req.query?.name) { + filter.name = { + $regex: new RegExp(req.query.name, "i"), + }; + } + if (req.query?.mobileNumber) { + filter.mobileNumber = { + $regex: new RegExp(req.query.mobileNumber, "i"), + }; + } + if (req.query?.isVerified) { + filter.isVerified = req.query.isVerified === "true"; + } + + const total = await TerritoryManager.countDocuments(filter); + const salesCoOrinators = await TerritoryManager.find(filter) + .limit(PAGE_SIZE) + .skip(PAGE_SIZE * page) + .sort({ createdAt: -1 }); + + return res.status(200).json({ + success: true, + total_data: total, + total_pages: Math.ceil(total / PAGE_SIZE), + salesCoOrinators, + }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went wrong!", + }); + } +}; + +export const getOneTerritoryManager = async (req, res) => { + try { + if (!req.params.id) { + return res + .status(400) + .json({ message: "Please provide sales coordinator ID" }); + } + const territoryManager = await TerritoryManager.findById(req.params.id); + if (territoryManager) { + return res.status(200).json({ + success: true, + message: "Fetched successfully", + data: territoryManager, + }); + } else { + return res.status(404).json({ + success: false, + message: "Sales coordinator not found", + }); + } + } catch (error) { + return res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went wrong!", + }); + } +}; + +// 4.Forgot Password + +export const forgotPassword = async (req, res) => { + const territorymanager = await TerritoryManager.findOne({ + email: req.body.email, + }); + if (!req.body.email) { + return res.status(400).json({ message: "please Enter Email!" }); + } + if (!territorymanager) { + return res.status(404).json({ message: "TerritoryManager not found" }); + } + // Get ResetPassword Token + // const resetToken = territorymanager.getResetPasswordToken(); //call function + + //save database reset token + // await territorymanager.save({ validateBeforeSave: false }); + + const passwords = password.randomPassword({ + length: 12, + characters: [ + { characters: password.upper, exactly: 1 }, + { characters: password.symbols, exactly: 1 }, + password.lower, + password.digits, + ], + }); + // console.log(passwords); + territorymanager.password = passwords; + await territorymanager.save(); + // const message = `Your password reset token are :- \n\n ${resetPasswordUrl} \n\nyour new password is:${password}\n\nIf you have not requested this email then, please ignore it.`; + try { + await sendEmail({ + to: `${territorymanager?.email}`, // Change to your recipient + + from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender + + subject: `Cheminova Password Recovery`, + html: `your new password is:
${passwords}

If you have not requested this email then, please ignore it.`, + }); + + res.status(200).json({ + success: true, + message: `Email sent to ${territorymanager?.email} successfully`, + }); + } catch (error) { + territorymanager.resetPasswordToken = undefined; + territorymanager.resetPasswordExpire = undefined; + + await territorymanager.save({ validateBeforeSave: false }); + + return res.status(500).json({ + message: error.message ? error.message : "Something went wrong!", + }); + } +}; + +//Update mobile Number +export const updateMobileNumber = async (req, res) => { + const { id } = req.params; + const userId = id || req.user._id; + let { newCountryCode, newMobileNumber } = req.body; + newCountryCode = newCountryCode?.trim(); + newMobileNumber = newMobileNumber?.trim(); + const newFullMobileNumber = `${newCountryCode}${newMobileNumber}`; + + try { + const territorymanager = await TerritoryManager.findById(userId); + if (!territorymanager) { + return res.status(400).json({ message: "TerritoryManager not found" }); + } + if (territorymanager.mobileNumber === newFullMobileNumber) { + return res.status(400).json({ + message: + "New mobile number cannot be the same as the old mobile number", + }); + } + // Check if the new mobile number already exists in another document + const existingTerritoryManager = await TerritoryManager.findOne({ + mobileNumber: newFullMobileNumber, + }); + + if (existingTerritoryManager) { + return res.status(400).json({ + message: "Mobile number already registered and verified by someone", + }); + } + // const otp = crypto.randomInt(100000, 1000000).toString(); + const otp = "123456"; + const otpExpires = Date.now() + 3 * 60 * 1000; // 3 minutes + + territorymanager.newMobileNumber = newFullMobileNumber; + territorymanager.otp = otp; + territorymanager.otpExpires = otpExpires; + + await territorymanager.save(); + await sendOtp( + newFullMobileNumber, + `Your Cheminova verification OTP is: ${otp}` + ); + + return res.status(200).json({ + message: `OTP sent to your new mobile number ${newFullMobileNumber} successfully`, + }); + } catch (error) { + console.error("Error updating mobile number:", error); + return res.status(500).json({ + message: error.message ? error.message : "Server error!", + }); + } +}; + +//verify Updated Number OTP +export const verifyUpdatedMobileOtp = async (req, res) => { + const { newMobileNumber, otp } = req.body; + // console.log(newMobileNumber, otp); + try { + let mobileNmr = newMobileNumber?.trim(); + const territoryManager = await TerritoryManager.findOne({ + newMobileNumber: mobileNmr, + }); + + if (!territoryManager) { + return res.status(400).json({ message: "Invalid mobile number or OTP" }); + } + + if ( + territoryManager.otp !== otp || + territoryManager.otpExpires < Date.now() + ) { + return res.status(400).json({ message: "Invalid or expired OTP" }); + } + + // Update sales coordinator's mobile number and verification status + territoryManager.mobileNumber = territoryManager.newMobileNumber; + territoryManager.newMobileNumber = undefined; + territoryManager.isVerified = true; + territoryManager.otp = undefined; + territoryManager.otpExpires = undefined; + + // Save changes to the database + await territoryManager.save(); + + const token = territoryManager.getJWTToken(); + return res.status(200).json({ + success: true, + token, + message: "Mobile number updated and verified successfully", + }); + } catch (error) { + console.error("Error verifying mobile OTP:", error); + return res.status(500).json({ + message: error.message ? error.message : "Server error!", + }); + } +}; + +//getmyProfile +export const getmyProfile = async (req, res) => { + try { + const myData = await TerritoryManager.findById(req.user?._id); + if (myData) { + return res.status(200).json({ + success: true, + message: "feched!", + myData, + }); + } + } catch (error) { + return res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went wrong!", + }); + } +}; + +// +export const deleteTerritoryManager = async (req, res) => { + try { + if (!req.params.id) { + return res.status(400).json({ + success: false, + message: "Please Provide TerritoryManager ID!", + }); + } + const getTerritoryManager = await TerritoryManager.findById(req.params.id); + if (!getTerritoryManager) { + return res.status(404).json({ + success: false, + message: "territorymanager not Found!", + }); + } + + //-------------------------// + const territorymanager = await TerritoryManager.findByIdAndDelete( + req.params.id + ); + if (!territorymanager) { + return res.status(404).json({ message: "territorymanager Not Found" }); + } + await territorymanager.remove(); + res.status(200).json({ + success: true, + message: "territorymanager Deleted Successfully!!", + }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went wrong!", + }); + } +}; + +export const UpdateProfile = async (req, res) => { + const { name, email } = req.body; + const { id } = req.params; + // console.log(name, email); + const userId = id || req.user._id; + // console.log(userId); + // Validate email + if (!validator.isEmail(email)) { + return res.status(400).json({ message: "Invalid email address" }); + } + + try { + const territoryManager = await TerritoryManager.findById(userId); // Use the ID from params + + if (!territoryManager) { + return res.status(404).json({ message: "TerritoryManager not found" }); + } + + if (!territoryManager.isVerified) { + return res.status(400).json({ message: "TerritoryManager not verified" }); + } + + // Check if email is being changed and already exists + if (email && email !== territoryManager.email) { + const emailExists = await TerritoryManager.findOne({ email }); + if (emailExists && emailExists._id.toString() !== userId) { + return res.status(400).json({ + message: + "This Email ID is already in use by another TerritoryManager", + }); + } + territoryManager.email = email; + } + + // Update name if provided + if (name) { + territoryManager.name = name; + } + + // Save the updated territoryManager + await territoryManager.save(); + + return res.status(200).json({ + territoryManager, + message: "Profile updated successfully", + }); + } catch (error) { + res.status(500).json({ + message: error.message ? error.message : "Server error!", + }); + } +}; + +//change TerritoryManager password +export const ChangePassword = async (req, res) => { + const { id } = req.params; // Retrieve id from req.params + const { oldPassword, newPassword, confirmPassword } = req.body; + const userId = id || req.user._id; // Use the ID from the URL or from the authenticated user + + 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 territorymanager = await TerritoryManager.findById(userId).select( + "+password" + ); + + if (!territorymanager) { + return res.status(404).json({ message: "TerritoryManager not found" }); + } + + const isPasswordMatched = await territorymanager.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" }); + } + + territorymanager.password = newPassword; + await territorymanager.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 Otp = async (req, res) => { + // const { name, mobileNumber } = req.body; + try { + // let territorymanager = await TerritoryManager.findOne({ mobileNumber }); + + // if (territorymanager && territorymanager.isVerified) { + // return res.status(400).json({ message: 'TerritoryManager already registered and verified for This Mobile No.' }); + // } + + // const otp = crypto.randomInt(100000, 1000000).toString(); + + // // const otp ="123456"; + + // const otpExpires = Date.now() + 10 * 60 * 1000; // 10 minutes + + // if (territorymanager) { + // territorymanager.otp = otp; + // territorymanager.otpExpires = otpExpires; + // } else { + // territorymanager = new TerritoryManager({ name, mobileNumber, otp, otpExpires }); + // } + + // await territorymanager.save(); + await sendOtp(); + + // res.status(200).json({territorymanager, message: `OTP ${otp} sent to your mobile number successfully` }); + } catch (error) { + res.status(500).json({ + message: error.message ? error.message : "Server error!", + }); + } +}; diff --git a/resources/TerritoryManagers/TerritoryManagerModel.js b/resources/TerritoryManagers/TerritoryManagerModel.js new file mode 100644 index 0000000..e1a0e10 --- /dev/null +++ b/resources/TerritoryManagers/TerritoryManagerModel.js @@ -0,0 +1,100 @@ +import dotenv from "dotenv"; +dotenv.config(); +import mongoose from "mongoose"; +import validator from "validator"; +import bcrypt from "bcryptjs"; +import jwt from "jsonwebtoken"; +import crypto from "crypto"; + +const territorymanagerSchema = new mongoose.Schema( + { + name: { + type: String, + required: true, + }, + mobileNumber: { + type: String, + required: true, + unique: true, + }, + otp: { + type: String, + required: false, + }, + otpExpires: { + type: Date, + }, + isVerified: { + type: Boolean, + default: false, + }, + email: { + type: String, + required: false, + unique: true, + validate: [validator.isEmail, "Please enter a valid Email"], + }, + password: { + type: String, + minLength: [6, "Password should be greater than 6 characters"], + select: false, + }, + newMobileNumber: { type: String }, + resetPasswordToken: String, + resetPasswordExpire: Date, + uniqueId: { + type: String, + unique: true, + required: true, + }, + }, + { timestamps: true } +); + +territorymanagerSchema.pre("save", async function (next) { + if (!this.isModified("password")) { + next(); + } + + this.password = await bcrypt.hash(this.password, 10); +}); + +territorymanagerSchema.pre("save", function (next) { + if (!this.uniqueId) { + const currentYear = new Date().getFullYear().toString().slice(-2); + const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase(); + this.uniqueId = `${currentYear}-${randomChars}`; + } + next(); +}); + +// JWT TOKEN +territorymanagerSchema.methods.getJWTToken = function () { + return jwt.sign({ id: this._id }, process.env.JWT_SECRET); +}; + +// Compare Password +territorymanagerSchema.methods.comparePassword = async function (password) { + return await bcrypt.compare(password, this.password); +}; + +// Generating Reset Token +territorymanagerSchema.methods.getResetPasswordToken = function () { + const resetToken = crypto.randomBytes(20).toString("hex"); + + this.resetPasswordToken = crypto + .createHash("sha256") + .update(resetToken) + .digest("hex"); + + this.resetPasswordExpire = Date.now() + 15 * 60 * 1000; // 15 minutes + + return resetToken; +}; + +const TerritoryManager = mongoose.model( + "TerritoryManager", + territorymanagerSchema +); + +export default TerritoryManager; diff --git a/resources/TerritoryManagers/TerritoryManagerRoute.js b/resources/TerritoryManagers/TerritoryManagerRoute.js new file mode 100644 index 0000000..82ee8c5 --- /dev/null +++ b/resources/TerritoryManagers/TerritoryManagerRoute.js @@ -0,0 +1,100 @@ +import express from "express"; + +const router = express.Router(); +import { + Otp, + deleteTerritoryManager, + forgotPassword, + getAllTerritoryManager, + loginTerritoryManager, + register, + updateMobileNumber, + verifyUpdatedMobileOtp, + verifyOtp, + UpdateProfile, + getmyProfile, + ChangePassword, + getOneTerritoryManager, + logout, +} from "./TerritoryManagerController.js"; +import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js"; +import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js"; + +router.post("/register", register); +router.post("/verify-otp", verifyOtp); +router.post("/login", loginTerritoryManager); +router.route("/logout").get(logout); +//admin +router.get( + "/getAll", + isAuthenticatedUser, + authorizeRoles("admin"), + getAllTerritoryManager +); +router.get( + "/getOne/:id", + isAuthenticatedUser, + authorizeRoles("admin"), + getOneTerritoryManager +); +router.get("/my-profile", isAuthenticatedTerritoryManager, getmyProfile); + +//Update Mobile Number +router.post( + "/update-mobile-number/:id", + isAuthenticatedUser, + authorizeRoles("admin"), + updateMobileNumber +); +router.post( + "/update-mobile-number", + isAuthenticatedTerritoryManager, + updateMobileNumber +); +router.post( + "/verify-updated-mobile-otp", + isAuthenticatedUser, + authorizeRoles("admin"), + verifyUpdatedMobileOtp +); +router.post( + "/verify-updated-mobilenumber-otp", + isAuthenticatedTerritoryManager, + verifyUpdatedMobileOtp +); +router.post("/forgot-password", forgotPassword); +router.patch( + "/profile/update/:id", + isAuthenticatedUser, + authorizeRoles("admin"), + UpdateProfile +); +router.patch( + "/profile/update", + isAuthenticatedTerritoryManager, + UpdateProfile +); +//change password +router.put( + "/password/update/:id", + isAuthenticatedUser, + authorizeRoles("admin"), + ChangePassword +); + +router.put( + "/password/update", + isAuthenticatedTerritoryManager, + ChangePassword +); +//delete TerritoryManager +router.delete( + "/delete/:id", + isAuthenticatedUser, + authorizeRoles("admin"), + deleteTerritoryManager +); + +router.get("/otp", Otp); + +export default router;