├── .gitignore ├── uploads ├── 2023-09-10T12-13-46.099Z-logo.jpg ├── 2024-07-31T05-57-10.102Z-po.png ├── 2024-07-31T13-16-52.657Z-ed2.png ├── 2023-09-06T10-57-37.905Z-cover-subhome.jpg ├── 2023-09-07T03-59-22.450Z-cover-subhome.jpg ├── 2023-09-10T12-09-23.402Z-cover-subhome.jpg ├── 2023-09-10T12-21-16.414Z-cover-subhome.jpg ├── 2023-09-10T13-50-35.685Z-crs_3_4b42a0ac72.jpg ├── 2023-09-10T13-51-07.154Z-crs_5_9c4cec97f2.jpg ├── 2024-07-31T11-33-51.550Z-Untitled-1 asajj.png ├── 2023-09-07T10-14-27.308Z-pelican-7962189_640.jpg ├── 2023-09-07T10-33-51.416Z-pelican-7962189_640.jpg ├── 2023-09-07T14-54-20.804Z-pelican-7962189_640.jpg ├── 2023-09-07T15-30-35.174Z-pelican-7962189_640.jpg ├── 2023-09-07T15-59-36.336Z-couple-8161451_1920.jpg ├── 2023-09-08T07-52-13.759Z-pelican-7962189_640.jpg ├── 2023-09-10T12-15-34.006Z-homes-8194751_1280.png ├── 2023-09-10T12-21-58.787Z-homes-8194751_1280.png ├── 2023-09-10T13-45-56.967Z-couple-8161451_1920.jpg ├── 2023-09-10T13-51-28.858Z-static_3_8df77a9c02.jpg ├── 2023-09-10T13-51-51.519Z-static_2_99b2fea38d.jpg ├── 2023-09-10T13-52-20.012Z-static_1_994dcbb547.jpg ├── 2023-09-07T12-04-40.270Z-portrait-8036356_640.jpg ├── 2023-09-07T13-43-39.730Z-portrait-8036356_640.jpg ├── 2023-09-07T14-50-36.348Z-portrait-8036356_640.jpg ├── 2023-09-07T14-51-47.769Z-portrait-8036356_640.jpg ├── 2023-09-07T14-52-27.954Z-portrait-8036356_640.jpg ├── 2023-09-07T14-53-27.356Z-portrait-8036356_640.jpg ├── 2023-09-07T15-00-09.102Z-portrait-8036356_640.jpg ├── 2023-09-07T15-02-05.307Z-portrait-8036356_640.jpg ├── 2023-09-07T15-03-17.863Z-portrait-8036356_640.jpg ├── 2023-09-07T15-03-29.481Z-portrait-8036356_640.jpg ├── 2023-09-07T15-08-51.514Z-portrait-8036356_640.jpg ├── 2023-09-07T15-15-29.751Z-portrait-8036356_640.jpg ├── 2023-09-07T15-17-43.955Z-portrait-8036356_640.jpg ├── 2023-09-07T15-18-30.919Z-portrait-8036356_640.jpg ├── 2023-09-07T15-20-27.589Z-portrait-8036356_640.jpg ├── 2023-09-07T15-22-30.241Z-portrait-8036356_640.jpg ├── 2023-09-07T15-23-12.578Z-portrait-8036356_640.jpg ├── 2023-09-07T16-01-19.266Z-7560944-230319073711.jpg ├── 2023-09-07T16-02-02.128Z-7560944-230319073711.jpg ├── 2023-09-07T16-02-21.111Z-7560944-230319073711.jpg ├── 2023-09-07T16-03-24.711Z-7560944-230319073711.jpg ├── 2023-09-07T16-04-58.891Z-7560944-230319073711.jpg ├── 2023-09-07T16-05-36.026Z-7560944-230319073711.jpg ├── 2023-09-07T16-06-38.052Z-7560944-230319073711.jpg ├── 2023-09-07T16-06-59.182Z-7560944-230319073711.jpg ├── 2023-09-07T16-07-49.134Z-7560944-230319073711.jpg ├── 2023-09-07T16-09-55.896Z-mushroom-8215265_1280.jpg ├── 2023-09-08T06-09-42.730Z-mushroom-8215265_1280.jpg ├── 2023-09-10T12-16-05.995Z-dahlias-8215514_1920.jpg ├── 2023-09-10T13-44-39.682Z-pexels-photo-807598.jpeg ├── 2023-09-10T13-45-07.667Z-mushroom-8215265_1280.jpg ├── 2023-09-10T13-45-30.372Z-dahlias-8215514_1920.jpg ├── 2023-09-08T09-33-48.376Z-architecture-7857833_1920.jpg ├── 2023-09-10T13-46-52.052Z-architecture-7857833_1920.jpg ├── 2023-09-21T10-47-39.212Z-istockphoto-1345772841-612x612.jpg ├── 2023-09-21T11-21-41.920Z-istockphoto-1289461328-612x612.jpg ├── 2023-09-21T11-29-38.870Z-istockphoto-1345772841-612x612.jpg ├── 2023-09-21T11-35-12.400Z-istockphoto-1338262936-612x612.jpg ├── 2023-09-21T11-40-28.158Z-istockphoto-1345772841-612x612.jpg ├── 2024-07-31T12-30-56.507Z-Black Gold Simple Initial Logo.png ├── 2024-07-31T05-47-12.506Z-Navy White University Elegant Logo.png ├── 2024-07-31T05-52-19.489Z-Navy White University Elegant Logo.png ├── 2024-07-31T12-51-51.430Z-Navy White University Elegant Logo.png ├── 2024-07-31T12-52-08.429Z-Navy White University Elegant Logo.png ├── 2024-07-31T12-52-14.025Z-Navy White University Elegant Logo.png ├── 2024-08-02T12-59-13.299Z-Red Black Minimalist Exotic Cars Logo.png └── 2024-08-02T13-05-27.196Z-Blue Modern Dance Channel Youtube Banner.png ├── middleWare ├── errorMiddleWare.js └── authMiddleWare.js ├── routes ├── biddingRoute.js ├── categoryRoute.js ├── userRoute.js └── productRoute.js ├── model ├── categoryModel.js ├── biddingProductModel.js ├── userModel.js └── productModel.js ├── utils ├── fileUpload.js └── sendEmail.js ├── package.json ├── server.js └── controllers ├── categoryController.js ├── biddingCtr.js ├── userCtr.js └── productCtr.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | .env -------------------------------------------------------------------------------- /uploads/2023-09-10T12-13-46.099Z-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T12-13-46.099Z-logo.jpg -------------------------------------------------------------------------------- /uploads/2024-07-31T05-57-10.102Z-po.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2024-07-31T05-57-10.102Z-po.png -------------------------------------------------------------------------------- /uploads/2024-07-31T13-16-52.657Z-ed2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2024-07-31T13-16-52.657Z-ed2.png -------------------------------------------------------------------------------- /uploads/2023-09-06T10-57-37.905Z-cover-subhome.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-06T10-57-37.905Z-cover-subhome.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T03-59-22.450Z-cover-subhome.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T03-59-22.450Z-cover-subhome.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T12-09-23.402Z-cover-subhome.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T12-09-23.402Z-cover-subhome.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T12-21-16.414Z-cover-subhome.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T12-21-16.414Z-cover-subhome.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T13-50-35.685Z-crs_3_4b42a0ac72.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T13-50-35.685Z-crs_3_4b42a0ac72.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T13-51-07.154Z-crs_5_9c4cec97f2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T13-51-07.154Z-crs_5_9c4cec97f2.jpg -------------------------------------------------------------------------------- /uploads/2024-07-31T11-33-51.550Z-Untitled-1 asajj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2024-07-31T11-33-51.550Z-Untitled-1 asajj.png -------------------------------------------------------------------------------- /uploads/2023-09-07T10-14-27.308Z-pelican-7962189_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T10-14-27.308Z-pelican-7962189_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T10-33-51.416Z-pelican-7962189_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T10-33-51.416Z-pelican-7962189_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T14-54-20.804Z-pelican-7962189_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T14-54-20.804Z-pelican-7962189_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-30-35.174Z-pelican-7962189_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-30-35.174Z-pelican-7962189_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-59-36.336Z-couple-8161451_1920.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-59-36.336Z-couple-8161451_1920.jpg -------------------------------------------------------------------------------- /uploads/2023-09-08T07-52-13.759Z-pelican-7962189_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-08T07-52-13.759Z-pelican-7962189_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T12-15-34.006Z-homes-8194751_1280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T12-15-34.006Z-homes-8194751_1280.png -------------------------------------------------------------------------------- /uploads/2023-09-10T12-21-58.787Z-homes-8194751_1280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T12-21-58.787Z-homes-8194751_1280.png -------------------------------------------------------------------------------- /uploads/2023-09-10T13-45-56.967Z-couple-8161451_1920.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T13-45-56.967Z-couple-8161451_1920.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T13-51-28.858Z-static_3_8df77a9c02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T13-51-28.858Z-static_3_8df77a9c02.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T13-51-51.519Z-static_2_99b2fea38d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T13-51-51.519Z-static_2_99b2fea38d.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T13-52-20.012Z-static_1_994dcbb547.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T13-52-20.012Z-static_1_994dcbb547.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T12-04-40.270Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T12-04-40.270Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T13-43-39.730Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T13-43-39.730Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T14-50-36.348Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T14-50-36.348Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T14-51-47.769Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T14-51-47.769Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T14-52-27.954Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T14-52-27.954Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T14-53-27.356Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T14-53-27.356Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-00-09.102Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-00-09.102Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-02-05.307Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-02-05.307Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-03-17.863Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-03-17.863Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-03-29.481Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-03-29.481Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-08-51.514Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-08-51.514Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-15-29.751Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-15-29.751Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-17-43.955Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-17-43.955Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-18-30.919Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-18-30.919Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-20-27.589Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-20-27.589Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-22-30.241Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-22-30.241Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T15-23-12.578Z-portrait-8036356_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T15-23-12.578Z-portrait-8036356_640.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T16-01-19.266Z-7560944-230319073711.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T16-01-19.266Z-7560944-230319073711.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T16-02-02.128Z-7560944-230319073711.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T16-02-02.128Z-7560944-230319073711.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T16-02-21.111Z-7560944-230319073711.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T16-02-21.111Z-7560944-230319073711.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T16-03-24.711Z-7560944-230319073711.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T16-03-24.711Z-7560944-230319073711.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T16-04-58.891Z-7560944-230319073711.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T16-04-58.891Z-7560944-230319073711.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T16-05-36.026Z-7560944-230319073711.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T16-05-36.026Z-7560944-230319073711.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T16-06-38.052Z-7560944-230319073711.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T16-06-38.052Z-7560944-230319073711.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T16-06-59.182Z-7560944-230319073711.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T16-06-59.182Z-7560944-230319073711.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T16-07-49.134Z-7560944-230319073711.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T16-07-49.134Z-7560944-230319073711.jpg -------------------------------------------------------------------------------- /uploads/2023-09-07T16-09-55.896Z-mushroom-8215265_1280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-07T16-09-55.896Z-mushroom-8215265_1280.jpg -------------------------------------------------------------------------------- /uploads/2023-09-08T06-09-42.730Z-mushroom-8215265_1280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-08T06-09-42.730Z-mushroom-8215265_1280.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T12-16-05.995Z-dahlias-8215514_1920.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T12-16-05.995Z-dahlias-8215514_1920.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T13-44-39.682Z-pexels-photo-807598.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T13-44-39.682Z-pexels-photo-807598.jpeg -------------------------------------------------------------------------------- /uploads/2023-09-10T13-45-07.667Z-mushroom-8215265_1280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T13-45-07.667Z-mushroom-8215265_1280.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T13-45-30.372Z-dahlias-8215514_1920.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T13-45-30.372Z-dahlias-8215514_1920.jpg -------------------------------------------------------------------------------- /uploads/2023-09-08T09-33-48.376Z-architecture-7857833_1920.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-08T09-33-48.376Z-architecture-7857833_1920.jpg -------------------------------------------------------------------------------- /uploads/2023-09-10T13-46-52.052Z-architecture-7857833_1920.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-10T13-46-52.052Z-architecture-7857833_1920.jpg -------------------------------------------------------------------------------- /uploads/2023-09-21T10-47-39.212Z-istockphoto-1345772841-612x612.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-21T10-47-39.212Z-istockphoto-1345772841-612x612.jpg -------------------------------------------------------------------------------- /uploads/2023-09-21T11-21-41.920Z-istockphoto-1289461328-612x612.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-21T11-21-41.920Z-istockphoto-1289461328-612x612.jpg -------------------------------------------------------------------------------- /uploads/2023-09-21T11-29-38.870Z-istockphoto-1345772841-612x612.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-21T11-29-38.870Z-istockphoto-1345772841-612x612.jpg -------------------------------------------------------------------------------- /uploads/2023-09-21T11-35-12.400Z-istockphoto-1338262936-612x612.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-21T11-35-12.400Z-istockphoto-1338262936-612x612.jpg -------------------------------------------------------------------------------- /uploads/2023-09-21T11-40-28.158Z-istockphoto-1345772841-612x612.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2023-09-21T11-40-28.158Z-istockphoto-1345772841-612x612.jpg -------------------------------------------------------------------------------- /uploads/2024-07-31T12-30-56.507Z-Black Gold Simple Initial Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2024-07-31T12-30-56.507Z-Black Gold Simple Initial Logo.png -------------------------------------------------------------------------------- /uploads/2024-07-31T05-47-12.506Z-Navy White University Elegant Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2024-07-31T05-47-12.506Z-Navy White University Elegant Logo.png -------------------------------------------------------------------------------- /uploads/2024-07-31T05-52-19.489Z-Navy White University Elegant Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2024-07-31T05-52-19.489Z-Navy White University Elegant Logo.png -------------------------------------------------------------------------------- /uploads/2024-07-31T12-51-51.430Z-Navy White University Elegant Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2024-07-31T12-51-51.430Z-Navy White University Elegant Logo.png -------------------------------------------------------------------------------- /uploads/2024-07-31T12-52-08.429Z-Navy White University Elegant Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2024-07-31T12-52-08.429Z-Navy White University Elegant Logo.png -------------------------------------------------------------------------------- /uploads/2024-07-31T12-52-14.025Z-Navy White University Elegant Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2024-07-31T12-52-14.025Z-Navy White University Elegant Logo.png -------------------------------------------------------------------------------- /uploads/2024-08-02T12-59-13.299Z-Red Black Minimalist Exotic Cars Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2024-08-02T12-59-13.299Z-Red Black Minimalist Exotic Cars Logo.png -------------------------------------------------------------------------------- /uploads/2024-08-02T13-05-27.196Z-Blue Modern Dance Channel Youtube Banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunil9813/Bid-Out-Backend/HEAD/uploads/2024-08-02T13-05-27.196Z-Blue Modern Dance Channel Youtube Banner.png -------------------------------------------------------------------------------- /middleWare/errorMiddleWare.js: -------------------------------------------------------------------------------- 1 | const errorHandler = (err, req, res, next) => { 2 | const statusCode = res.statusCode ? res.statusCode : 500; 3 | res.status(statusCode); 4 | 5 | res.json({ 6 | message: err.message, 7 | stack: process.env.NODE_ENV === "development" ? err.stack : null, 8 | }); 9 | }; 10 | module.exports = errorHandler; 11 | -------------------------------------------------------------------------------- /routes/biddingRoute.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { placeBid, getBiddingHistory, sellProduct } = require("../controllers/biddingCtr"); 3 | const { protect, isSeller } = require("../middleWare/authMiddleWare"); 4 | const router = express.Router(); 5 | 6 | router.get("/:productId", getBiddingHistory); 7 | router.post("/sell", protect, isSeller, sellProduct); 8 | router.post("/", protect, placeBid); 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /model/categoryModel.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const categorySchema = new mongoose.Schema( 4 | { 5 | user: { 6 | type: mongoose.Schema.Types.ObjectId, 7 | ref: "User", 8 | required: true, 9 | }, 10 | title: { 11 | type: String, 12 | required: [true, "Title is required"], 13 | }, 14 | }, 15 | { timestamps: true } 16 | ); 17 | 18 | const Category = mongoose.model("Category", categorySchema); 19 | module.exports = Category; 20 | -------------------------------------------------------------------------------- /model/biddingProductModel.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const BiddingProductSchema = mongoose.Schema( 4 | { 5 | user: { 6 | type: mongoose.Schema.Types.ObjectId, 7 | require: true, 8 | ref: "User", 9 | }, 10 | product: { 11 | type: mongoose.Schema.Types.ObjectId, 12 | require: true, 13 | ref: "Product", 14 | }, 15 | price: { 16 | type: Number, 17 | require: [true, "Please add a Price"], 18 | }, 19 | }, 20 | { timestamps: true } 21 | ); 22 | const biddingproduct = mongoose.model("BiddingProduct", BiddingProductSchema); 23 | module.exports = biddingproduct; 24 | -------------------------------------------------------------------------------- /utils/fileUpload.js: -------------------------------------------------------------------------------- 1 | const multer = require("multer") 2 | 3 | const storage = multer.diskStorage({ 4 | destination: function (req, file, cb) { 5 | cb(null, "uploads") 6 | }, 7 | filename: function (req, file, cb) { 8 | cb(null, new Date().toISOString().replace(/:/g, "-") + "-" + file.originalname) // 23/08/2022 9 | }, 10 | }) 11 | 12 | function fileFilter(req, file, cb) { 13 | if (file.mimetype === "image/png" || file.mimetype === "image/jpg" || file.mimetype === "image/jpeg") { 14 | cb(null, true) 15 | } else { 16 | cb(null, false) 17 | } 18 | } 19 | 20 | const upload = multer({ storage, fileFilter }) 21 | 22 | module.exports = { upload } 23 | -------------------------------------------------------------------------------- /routes/categoryRoute.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { 3 | createCategory, 4 | getAllCategory, 5 | getCategory, 6 | updateCategory, 7 | deleteCategory, 8 | } = require("../controllers/categoryController"); 9 | const { protect, isAdmin } = require("../middleWare/authMiddleWare"); 10 | 11 | const categoryRoute = express.Router(); 12 | 13 | categoryRoute.post("/", protect, isAdmin, createCategory); 14 | categoryRoute.get("/", getAllCategory); 15 | categoryRoute.get("/:id", protect, isAdmin, getCategory); 16 | categoryRoute.put("/:id", protect, isAdmin, updateCategory); 17 | categoryRoute.delete("/:id", protect, isAdmin, deleteCategory); 18 | 19 | module.exports = categoryRoute; 20 | -------------------------------------------------------------------------------- /utils/sendEmail.js: -------------------------------------------------------------------------------- 1 | const nodemailer = require("nodemailer"); 2 | 3 | const sendEmail = async (options) => { 4 | if (!options.email) { 5 | throw new Error("No recipients defined"); 6 | } 7 | const transport = nodemailer.createTransport({ 8 | host: process.env.SMPT_HOST, 9 | port: process.env.SMPT_PORT, 10 | auth: { 11 | user: process.env.SMPT_EMAIL, 12 | pass: process.env.SMPT_PASS, 13 | }, 14 | }); 15 | 16 | const message = { 17 | from: `${process.env.SMPT_FROM_NAME} <${process.env.SMPT_FROM_EMAIL}> `, 18 | to: options.email, 19 | subject: options.subject, 20 | text: options.message, 21 | }; 22 | 23 | await transport.sendMail(message); 24 | }; 25 | module.exports = sendEmail; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "bcryptjs": "^2.4.3", 4 | "body-parser": "^1.20.2", 5 | "cloudinary": "^1.36.4", 6 | "cookie-parser": "^1.4.6", 7 | "cors": "^2.8.5", 8 | "dotenv": "^16.0.3", 9 | "express": "^4.18.2", 10 | "express-async-handler": "^1.2.0", 11 | "i": "^0.3.7", 12 | "jsonwebtoken": "^9.0.0", 13 | "mongoose": "^7.1.0", 14 | "multer": "^1.4.5-lts.1", 15 | "node-schedule": "^2.1.1", 16 | "nodemailer": "^6.9.5", 17 | "path": "^0.12.7", 18 | "slugify": "^1.6.6" 19 | }, 20 | "scripts": { 21 | "start": "nodemon server.js" 22 | }, 23 | "name": "backend", 24 | "version": "1.0.0", 25 | "main": "server.js", 26 | "author": "Sunil BK", 27 | "license": "ISC", 28 | "description": "" 29 | } 30 | -------------------------------------------------------------------------------- /routes/userRoute.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | const { registerUser, loginUser, loginStatus, logoutUser, loginAsSeller, estimateIncome, getUser, getUserBalance, getAllUser } = require("../controllers/userCtr"); 4 | const { protect, isAdmin } = require("../middleWare/authMiddleWare"); 5 | 6 | router.post("/register", registerUser); 7 | router.post("/login", loginUser); 8 | router.get("/loggedin", loginStatus); 9 | router.get("/logout", logoutUser); 10 | router.post("/seller", loginAsSeller); 11 | router.get("/getuser", protect, getUser); 12 | router.get("/sell-amount", protect, getUserBalance); 13 | 14 | router.get("/estimate-income", protect, isAdmin, estimateIncome); 15 | router.get("/users", protect, isAdmin, getAllUser); 16 | 17 | module.exports = router; 18 | -------------------------------------------------------------------------------- /routes/productRoute.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { 3 | createProduct, 4 | getAllProducts, 5 | deleteProduct, 6 | updateProduct, 7 | getProductBySlug, 8 | getAllProductsByAmdin, 9 | deleteProductsByAmdin, 10 | getAllSoldProducts, 11 | verifyAndAddCommissionProductByAmdin, 12 | getAllProductsofUser, 13 | getWonProducts, 14 | } = require("../controllers/productCtr"); 15 | const { upload } = require("../utils/fileUpload"); 16 | const { protect, isSeller, isAdmin } = require("../middleWare/authMiddleWare"); 17 | const router = express.Router(); 18 | 19 | router.post("/", protect, isSeller, upload.single("image"), createProduct); 20 | router.delete("/:id", protect, isSeller, deleteProduct); 21 | router.put("/:id", protect, isSeller, upload.single("image"), updateProduct); 22 | 23 | router.get("/", getAllProducts); 24 | router.get("/user", protect, getAllProductsofUser); 25 | router.get("/won-products", protect, getWonProducts); 26 | router.get("/sold", getAllSoldProducts); 27 | router.get("/:id", getProductBySlug); 28 | 29 | // Only access for admin users 30 | router.patch("/admin/product-verified/:id", protect, isAdmin, verifyAndAddCommissionProductByAmdin); 31 | router.get("/admin/products", protect, isAdmin, getAllProductsByAmdin); 32 | router.delete("/admin/products", protect, isAdmin, deleteProductsByAmdin); 33 | 34 | module.exports = router; 35 | -------------------------------------------------------------------------------- /middleWare/authMiddleWare.js: -------------------------------------------------------------------------------- 1 | const expressAsyncHandler = require("express-async-handler"); 2 | const jwt = require("jsonwebtoken"); 3 | const User = require("../model/userModel"); 4 | 5 | const protect = expressAsyncHandler(async (req, res, next) => { 6 | try { 7 | const token = req.cookies.token; 8 | if (!token) { 9 | res.status(401); 10 | throw new Error("Not authorized, Please Login"); 11 | } 12 | const verified = jwt.verify(token, process.env.JWT_SECRET); 13 | const user = await User.findById(verified.id).select("-password"); 14 | if (!user) { 15 | res.status(401); 16 | throw new Error("User not found"); 17 | } 18 | req.user = user; 19 | next(); 20 | } catch (error) { 21 | res.status(401); 22 | throw new Error("Not authorized, Please Login"); 23 | } 24 | }); 25 | 26 | const isAdmin = (req, res, next) => { 27 | if (req.user && req.user.role === "admin") { 28 | next(); 29 | } else { 30 | res.status(403); 31 | throw new Error("Access denied. You are not an admin."); 32 | } 33 | }; 34 | 35 | const isSeller = (req, res, next) => { 36 | if (req.user && (req.user.role === "seller" || req.user.role === "admin")) { 37 | next(); 38 | } else { 39 | res.status(403); 40 | throw new Error("Access denied. You are not a seller."); 41 | } 42 | }; 43 | 44 | module.exports = { protect, isAdmin, isSeller }; 45 | -------------------------------------------------------------------------------- /model/userModel.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const bcrypt = require("bcryptjs"); 3 | 4 | const userSchema = mongoose.Schema( 5 | { 6 | name: { 7 | type: String, 8 | require: [true, "Please add a name"], 9 | }, 10 | email: { 11 | type: String, 12 | require: [true, "Please add a email"], 13 | unique: true, 14 | trim: true, 15 | match: [/^\s*[\w\-\+_]+(\.[\w\-\+_]+)*\@[\w\-\+_]+\.[\w\-\+_]+(\.[\w\-\+_]+)*\s*$/, "Please enter a valid email"], 16 | }, 17 | password: { 18 | type: String, 19 | require: [true, "Please add a password"], 20 | minLength: [8, "Password must be up to 8 characters"], 21 | }, 22 | photo: { 23 | type: String, 24 | require: [true, "Please add a photo"], 25 | default: "https://cdn-icons-png.flaticon.com/512/2202/2202112.png", 26 | }, 27 | role: { 28 | type: String, 29 | enum: ["admin", "seller", "buyer"], 30 | default: "buyer", 31 | }, 32 | commissionBalance: { 33 | type: Number, 34 | default: 0, 35 | }, 36 | balance: { 37 | type: Number, 38 | default: 0, 39 | }, 40 | }, 41 | { 42 | timestamps: true, 43 | } 44 | ); 45 | 46 | userSchema.pre("save", async function (next) { 47 | if (!this.isModified("password")) { 48 | return next(); 49 | } 50 | const salt = await bcrypt.genSalt(10); 51 | const hashedPassword = await bcrypt.hash(this.password, salt); 52 | this.password = hashedPassword; 53 | next(); 54 | }); 55 | const User = mongoose.model("User", userSchema); 56 | module.exports = User; 57 | -------------------------------------------------------------------------------- /model/productModel.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const productSchema = mongoose.Schema( 4 | { 5 | user: { 6 | type: mongoose.Schema.Types.ObjectId, 7 | require: true, 8 | ref: "User", 9 | }, 10 | title: { 11 | type: String, 12 | require: [true, "Please add a title"], 13 | trime: true, 14 | }, 15 | slug: { 16 | type: String, 17 | unique: true, 18 | }, 19 | description: { 20 | type: String, 21 | required: [true, "Please add a description"], 22 | trime: true, 23 | }, 24 | image: { 25 | type: Object, 26 | default: {}, 27 | }, 28 | category: { 29 | type: String, 30 | required: [true, "Post category is required"], 31 | default: "All", 32 | }, 33 | commission: { 34 | type: Number, 35 | default: 0, 36 | }, 37 | price: { 38 | type: Number, 39 | require: [true, "Please add a Price"], 40 | }, 41 | height: { 42 | type: Number, 43 | }, 44 | lengthpic: { 45 | type: Number, 46 | }, 47 | width: { 48 | type: Number, 49 | }, 50 | mediumused: { 51 | type: String, 52 | }, 53 | weigth: { 54 | type: Number, 55 | }, 56 | isverify: { 57 | type: Boolean, 58 | default: false, 59 | }, 60 | isSoldout: { 61 | type: Boolean, 62 | default: false, 63 | }, 64 | soldTo: { type: mongoose.Schema.Types.ObjectId, ref: "User" }, 65 | }, 66 | { timestamps: true } 67 | ); 68 | const product = mongoose.model("Product", productSchema); 69 | module.exports = product; 70 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const dotenv = require("dotenv").config(); 2 | const express = require("express"); 3 | const mongoose = require("mongoose"); 4 | const bodyParser = require("body-parser"); 5 | const cors = require("cors"); 6 | const path = require("path"); 7 | const cookieParser = require("cookie-parser"); 8 | 9 | const userRoute = require("./routes/userRoute"); 10 | const productRoute = require("./routes/productRoute"); 11 | const biddingRoute = require("./routes/biddingRoute"); 12 | const categoryRoute = require("./routes/categoryRoute"); 13 | const errorHandler = require("./middleWare/errorMiddleWare"); 14 | const User = require("./model/userModel"); 15 | 16 | const app = express(); 17 | 18 | //middlewares 19 | app.use(express.json()); 20 | app.use(cookieParser()); 21 | app.use( 22 | express.urlencoded({ 23 | extended: false, 24 | }) 25 | ); 26 | app.use(bodyParser.json()); 27 | 28 | app.use( 29 | cors({ 30 | origin: ["http://localhost:3000"], 31 | credentials: true, 32 | }) 33 | ); 34 | 35 | const PORT = process.env.PORT || 5000; 36 | 37 | //Routes Middleware 38 | app.use("/api/users", userRoute); 39 | app.use("/api/product", productRoute); 40 | app.use("/api/bidding", biddingRoute); 41 | app.use("/api/category", categoryRoute); 42 | 43 | app.use("/uploads", express.static(path.join(__dirname, "uploads"))); 44 | 45 | // Erro Middleware 46 | app.use(errorHandler); 47 | 48 | // Routes 49 | app.get("/", (req, res) => { 50 | res.send("Home Pages"); 51 | }); 52 | 53 | //connect to mongoose 54 | mongoose 55 | .connect(process.env.DATABASE_CLOUD, { 56 | useNewUrlParser: true, 57 | useUnifiedTopology: true, 58 | }) 59 | .then(() => { 60 | app.listen(PORT, () => { 61 | console.log(`Server Running on port ${PORT}`); 62 | }); 63 | }) 64 | .catch((err) => { 65 | console.log(err); 66 | }); 67 | -------------------------------------------------------------------------------- /controllers/categoryController.js: -------------------------------------------------------------------------------- 1 | const asyncHandler = require("express-async-handler"); 2 | const Category = require("../model/categoryModel"); 3 | 4 | const createCategory = asyncHandler(async (req, res) => { 5 | try { 6 | const existingCategory = await Category.findOne({ title: req.body.title }); 7 | if (existingCategory) { 8 | res.status(400).json({ message: "Category with this title already exists" }); 9 | return; 10 | } 11 | const category = await Category.create({ 12 | user: req.user._id, 13 | title: req.body.title, 14 | }); 15 | 16 | res.json(category); 17 | } catch (error) { 18 | res.status(500).json({ message: "Internal server error" }); 19 | } 20 | }); 21 | 22 | const getAllCategory = asyncHandler(async (req, res) => { 23 | try { 24 | const categories = await Category.find({}).populate("user").sort("-createAt"); 25 | res.json(categories); 26 | } catch (error) { 27 | res.json(error); 28 | } 29 | }); 30 | const getCategory = asyncHandler(async (req, res) => { 31 | const { id } = req.params; 32 | try { 33 | const categorie = await Category.findById(id).populate("user").sort("-createAt"); 34 | res.json(categorie); 35 | } catch (error) { 36 | res.json(error); 37 | } 38 | }); 39 | const updateCategory = asyncHandler(async (req, res) => { 40 | const { id } = req.params; 41 | try { 42 | const categorie = await Category.findByIdAndUpdate( 43 | id, 44 | { 45 | title: req?.body?.title, 46 | }, 47 | { 48 | new: true, 49 | runValidators: true, 50 | } 51 | ); 52 | res.json(categorie); 53 | } catch (error) { 54 | res.json(error); 55 | } 56 | }); 57 | const deleteCategory = asyncHandler(async (req, res) => { 58 | const { id } = req.params; 59 | try { 60 | await Category.findByIdAndDelete(id); 61 | res.status(200).json({ message: "Category deleted" }); 62 | } catch (error) { 63 | res.json(error); 64 | } 65 | }); 66 | module.exports = { createCategory, getAllCategory, getCategory, updateCategory, deleteCategory }; 67 | -------------------------------------------------------------------------------- /controllers/biddingCtr.js: -------------------------------------------------------------------------------- 1 | const asyncHandler = require("express-async-handler"); 2 | const Product = require("../model/productModel"); 3 | const BiddingProduct = require("../model/biddingProductModel"); 4 | const sendEmail = require("../utils/sendEmail"); 5 | const User = require("../model/userModel"); 6 | 7 | const placeBid = asyncHandler(async (req, res) => { 8 | const { productId, price } = req.body; 9 | const userId = req.user.id; 10 | 11 | const product = await Product.findById(productId); 12 | if (!product.isverify) { 13 | res.status(400); 14 | throw new Error("Bidding is not verified for these products."); 15 | } 16 | 17 | if (!product || product.isSoldout === true) { 18 | res.status(400); 19 | throw new Error("Invalid product or bidding is closed"); 20 | } 21 | 22 | /* if (price < product.minprice) { 23 | res.status(400); 24 | throw new Error("Your bid must be equal to or higher than the minimum bidding price"); 25 | } */ 26 | 27 | const existingUserBid = await BiddingProduct.findOne({ user: userId, product: productId }); 28 | 29 | if (existingUserBid) { 30 | if (price <= existingUserBid.price) { 31 | res.status(400); 32 | throw new Error("Your bid must be higher than your previous bid"); 33 | } 34 | existingUserBid.price = price; 35 | await existingUserBid.save(); 36 | res.status(200).json({ biddingProduct: existingUserBid }); 37 | } else { 38 | const highestBid = await BiddingProduct.findOne({ product: productId }).sort({ price: -1 }); 39 | if (highestBid && price <= highestBid.price) { 40 | res.status(400); 41 | throw new Error("Your bid must be higher than the current highest bid"); 42 | } 43 | 44 | const biddingProduct = await BiddingProduct.create({ 45 | user: userId, 46 | product: productId, 47 | price, 48 | }); 49 | 50 | res.status(201).json(biddingProduct); 51 | } 52 | }); 53 | 54 | const getBiddingHistory = asyncHandler(async (req, res) => { 55 | const { productId } = req.params; 56 | 57 | const biddingHistory = await BiddingProduct.find({ product: productId }).sort("-createdAt").populate("user").populate("product"); 58 | 59 | res.status(200).json(biddingHistory); 60 | }); 61 | 62 | const sellProduct = asyncHandler(async (req, res) => { 63 | const { productId } = req.body; 64 | const userId = req.user.id; 65 | 66 | // Find the product 67 | const product = await Product.findById(productId); 68 | if (!product) { 69 | return res.status(404).json({ error: "Product not found" }); 70 | } 71 | 72 | // /* const currentTime = new Date(); 73 | // const tenMinutesAgo = new Date(currentTime - 2 * 60 * 1000); // 10 minutes ago 74 | 75 | // if (!product.isSoldout || product.updatedAt < tenMinutesAgo || product.createdAt < tenMinutesAgo) { 76 | // return res.status(400).json({ error: "Product cannot be sold at this time" }); 77 | // } */ 78 | 79 | // Check if the user is authorized to sell the product 80 | if (product.user.toString() !== userId) { 81 | return res.status(403).json({ error: "You do not have permission to sell this product" }); 82 | } 83 | 84 | // Find the highest bid 85 | const highestBid = await BiddingProduct.findOne({ product: productId }).sort({ price: -1 }).populate("user"); 86 | if (!highestBid) { 87 | return res.status(400).json({ error: "No winning bid found for the product" }); 88 | } 89 | 90 | // Calculate commission and final price 91 | const commissionRate = product.commission; 92 | const commissionAmount = (commissionRate / 100) * highestBid.price; 93 | const finalPrice = highestBid.price - commissionAmount; 94 | 95 | // Update product details 96 | product.isSoldout = true; 97 | product.soldTo = highestBid.user; 98 | product.soldPrice = finalPrice; 99 | 100 | // Update admin's commission balance 101 | const admin = await User.findOne({ role: "admin" }); 102 | if (admin) { 103 | admin.commissionBalance += commissionAmount; 104 | await admin.save(); 105 | } 106 | 107 | // Update seller's balance 108 | const seller = await User.findById(product.user); 109 | if (seller) { 110 | seller.balance += finalPrice; // Add the remaining amount to the seller's balance 111 | await seller.save(); 112 | } else { 113 | return res.status(404).json({ error: "Seller not found" }); 114 | } 115 | 116 | // Save product 117 | await product.save(); 118 | 119 | // Send email notification to the highest bidder 120 | await sendEmail({ 121 | email: highestBid.user.email, 122 | subject: "Congratulations! You won the auction!", 123 | text: `You have won the auction for "${product.title}" with a bid of $${highestBid.price}.`, 124 | }); 125 | 126 | res.status(200).json({ message: "Product has been successfully sold!" }); 127 | }); 128 | 129 | module.exports = { 130 | placeBid, 131 | getBiddingHistory, 132 | sellProduct, 133 | }; 134 | -------------------------------------------------------------------------------- /controllers/userCtr.js: -------------------------------------------------------------------------------- 1 | const asyncHandler = require("express-async-handler"); 2 | const User = require("../model/userModel"); 3 | const jwt = require("jsonwebtoken"); 4 | const bcrypt = require("bcryptjs"); 5 | const Product = require("../model/productModel"); 6 | 7 | const generateToken = (id) => { 8 | return jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: "1d" }); 9 | }; 10 | 11 | const registerUser = asyncHandler(async (req, res) => { 12 | const { name, email, password } = req.body; 13 | 14 | if (!name || !email || !password) { 15 | res.status(400); 16 | throw new Error("Please fill in all required fileds"); 17 | } 18 | 19 | const userExits = await User.findOne({ email }); 20 | if (userExits) { 21 | res.status(400); 22 | throw new Error("Email is already exit"); 23 | } 24 | 25 | const user = await User.create({ 26 | name, 27 | email, 28 | password, 29 | }); 30 | 31 | const token = generateToken(user._id); 32 | res.cookie("token", token, { 33 | path: "/", 34 | httpOnly: true, 35 | expires: new Date(Date.now() + 1000 * 86400), // 1 day 36 | sameSite: "none", 37 | secure: true, 38 | }); 39 | 40 | if (user) { 41 | const { _id, name, email, photo, role } = user; 42 | res.status(201).json({ _id, name, email, photo, token, role }); 43 | } else { 44 | res.status(400); 45 | throw new Error("Invalid user data"); 46 | } 47 | }); 48 | 49 | const loginUser = asyncHandler(async (req, res) => { 50 | const { email, password } = req.body; 51 | 52 | if (!email || !password) { 53 | res.status(400); 54 | throw new Error("Please add Email and Password"); 55 | } 56 | const user = await User.findOne({ email }); 57 | if (!user) { 58 | res.status(400); 59 | throw new Error("User not found, Please signUp"); 60 | } 61 | 62 | const passwordIsCorrrect = await bcrypt.compare(password, user.password); 63 | 64 | const token = generateToken(user._id); 65 | res.cookie("token", token, { 66 | path: "/", 67 | httpOnly: true, 68 | expires: new Date(Date.now() + 1000 * 86400), // 1 day 69 | sameSite: "none", 70 | secure: true, 71 | }); 72 | 73 | if (user && passwordIsCorrrect) { 74 | const { _id, name, email, photo, role } = user; 75 | res.status(201).json({ _id, name, email, photo, role, token }); 76 | } else { 77 | res.status(400); 78 | throw new Error("Invalid email or password"); 79 | } 80 | }); 81 | 82 | const loginStatus = asyncHandler(async (req, res) => { 83 | const token = req.cookies.token; 84 | if (!token) { 85 | return res.json(false); 86 | } 87 | const verified = jwt.verify(token, process.env.JWT_SECRET); 88 | if (verified) { 89 | return res.json(true); 90 | } 91 | return res.json(false); 92 | }); 93 | 94 | const getUser = asyncHandler(async (req, res) => { 95 | const user = await User.findById(req.user._id).select("-password"); 96 | 97 | res.status(200).json(user); 98 | }); 99 | 100 | const logoutUser = asyncHandler(async (req, res) => { 101 | res.cookie("token", "", { 102 | path: "/", 103 | httpOnly: true, 104 | expires: new Date(0), 105 | sameSite: "none", 106 | secure: true, 107 | }); 108 | return res.status(200).json({ message: "Successfully Logged Out" }); 109 | }); 110 | 111 | /* const loginAsSeller = asyncHandler(async (req, res) => { 112 | const { email, password } = req.body; 113 | 114 | if (!email || !password) { 115 | res.status(400); 116 | throw new Error("Please add Email and Password"); 117 | } 118 | const user = await User.findOne({ email }); 119 | if (!user) { 120 | res.status(400); 121 | throw new Error("User not found, Please signUp"); 122 | } 123 | 124 | const passwordIsCorrrect = await bcrypt.compare(password, user.password); 125 | 126 | const token = generateToken(user._id); 127 | 128 | res.cookie("token", token, { 129 | path: "/", 130 | httpOnly: true, 131 | expires: new Date(Date.now() + 1000 * 86400), 132 | sameSite: "none", 133 | secure: true, 134 | }); 135 | 136 | user.role = "seller"; 137 | user.save(); 138 | if (user && passwordIsCorrrect) { 139 | const { _id, name, email, photo, role } = user; 140 | res.status(201).json({ _id, name, email, photo, role, token }); 141 | } else { 142 | res.status(400); 143 | throw new Error("Invalid email or password"); 144 | } 145 | }); */ 146 | const loginAsSeller = asyncHandler(async (req, res) => { 147 | const { email, password } = req.body; 148 | 149 | // Check if email and password are provided 150 | if (!email || !password) { 151 | res.status(400); 152 | throw new Error("Please provide both email and password"); 153 | } 154 | 155 | // Find the user by email 156 | const user = await User.findOne({ email }); 157 | if (!user) { 158 | res.status(400); 159 | throw new Error("User not found, please sign up"); 160 | } 161 | 162 | // Verify the password 163 | const passwordIsCorrect = await bcrypt.compare(password, user.password); 164 | if (!passwordIsCorrect) { 165 | res.status(400); 166 | throw new Error("Invalid email or password"); 167 | } 168 | 169 | // If password is correct, update the role to 'seller' 170 | user.role = "seller"; 171 | await user.save(); 172 | 173 | // Generate a token and set cookie 174 | const token = generateToken(user._id); 175 | res.cookie("token", token, { 176 | path: "/", 177 | httpOnly: true, 178 | expires: new Date(Date.now() + 1000 * 86400), 179 | sameSite: "none", 180 | secure: true, 181 | }); 182 | 183 | // Send the response with updated user info 184 | const { _id, name, email: userEmail, photo, role } = user; 185 | res.status(200).json({ _id, name, email: userEmail, photo, role, token }); 186 | }); 187 | 188 | const getUserBalance = asyncHandler(async (req, res) => { 189 | const user = await User.findById(req.user.id); 190 | 191 | if (!user) { 192 | res.status(404); 193 | throw new Error("User not found"); 194 | } 195 | 196 | res.status(200).json({ 197 | balance: user.balance, 198 | }); 199 | }); 200 | 201 | // Only for admin users 202 | const getAllUser = asyncHandler(async (req, res) => { 203 | const userList = await User.find({}); 204 | 205 | if (!userList.length) { 206 | return res.status(404).json({ message: "No user found" }); 207 | } 208 | 209 | res.status(200).json(userList); 210 | }); 211 | 212 | const estimateIncome = asyncHandler(async (req, res) => { 213 | try { 214 | const admin = await User.findOne({ role: "admin" }); 215 | if (!admin) { 216 | return res.status(404).json({ error: "Admin user not found" }); 217 | } 218 | const commissionBalance = admin.commissionBalance; 219 | res.status(200).json({ commissionBalance }); 220 | } catch (error) { 221 | console.error(error); 222 | res.status(500).json({ error: "Internal server error" }); 223 | } 224 | }); 225 | module.exports = { 226 | registerUser, 227 | loginUser, 228 | loginStatus, 229 | logoutUser, 230 | loginAsSeller, 231 | estimateIncome, 232 | getUser, 233 | getUserBalance, 234 | getAllUser, 235 | }; 236 | -------------------------------------------------------------------------------- /controllers/productCtr.js: -------------------------------------------------------------------------------- 1 | const asyncHandler = require("express-async-handler"); 2 | const Product = require("../model/productModel"); 3 | const slugify = require("slugify"); 4 | const BiddingProduct = require("../model/biddingProductModel"); 5 | const cloudinary = require("cloudinary").v2; 6 | 7 | const createProduct = asyncHandler(async (req, res) => { 8 | const { title, description, price, category, height, lengthpic, width, mediumused, weigth } = req.body; 9 | const userId = req.user.id; 10 | 11 | const originalSlug = slugify(title, { 12 | lower: true, 13 | remove: /[*+~.()'"!:@]/g, 14 | strict: true, 15 | }); 16 | 17 | let slug = originalSlug; 18 | let suffix = 1; 19 | 20 | while (await Product.findOne({ slug })) { 21 | slug = `${originalSlug}-${suffix}`; 22 | suffix++; 23 | } 24 | 25 | if (!title || !description || !price) { 26 | res.status(400); 27 | throw new Error("Please fill in all fields"); 28 | } 29 | 30 | let fileData = {}; 31 | if (req.file) { 32 | let uploadedFile; 33 | try { 34 | uploadedFile = await cloudinary.uploader.upload(req.file.path, { 35 | folder: "Bidding/Product", 36 | resource_type: "image", 37 | }); 38 | } catch (error) { 39 | res.status(500); 40 | throw new Error("Image could not be uploaded"); 41 | } 42 | 43 | fileData = { 44 | fileName: req.file.originalname, 45 | filePath: uploadedFile.secure_url, 46 | fileType: req.file.mimetype, 47 | public_id: uploadedFile.public_id, 48 | }; 49 | } 50 | 51 | const product = await Product.create({ 52 | user: userId, 53 | title, 54 | slug: slug, 55 | description, 56 | price, 57 | category, 58 | height, 59 | lengthpic, 60 | width, 61 | mediumused, 62 | weigth, 63 | image: fileData, 64 | }); 65 | res.status(201).json({ 66 | success: true, 67 | data: product, 68 | }); 69 | }); 70 | 71 | const getAllProducts = asyncHandler(async (req, res) => { 72 | const products = await Product.find({}).sort("-createdAt").populate("user"); 73 | 74 | const productsWithDetails = await Promise.all( 75 | products.map(async (product) => { 76 | const latestBid = await BiddingProduct.findOne({ product: product._id }).sort("-createdAt"); 77 | const biddingPrice = latestBid ? latestBid.price : product.price; 78 | 79 | const totalBids = await BiddingProduct.countDocuments({ product: product._id }); 80 | 81 | return { 82 | ...product._doc, 83 | biddingPrice, 84 | totalBids, // Adding the total number of bids 85 | }; 86 | }) 87 | ); 88 | 89 | res.status(200).json(productsWithDetails); 90 | }); 91 | 92 | const getAllProductsofUser = asyncHandler(async (req, res) => { 93 | const userId = req.user._id; 94 | 95 | const products = await Product.find({ user: userId }).sort("-createdAt").populate("user"); 96 | 97 | const productsWithPrices = await Promise.all( 98 | products.map(async (product) => { 99 | const latestBid = await BiddingProduct.findOne({ product: product._id }).sort("-createdAt"); 100 | const biddingPrice = latestBid ? latestBid.price : product.price; 101 | return { 102 | ...product._doc, 103 | biddingPrice, // Adding the price field 104 | }; 105 | }) 106 | ); 107 | 108 | res.status(200).json(productsWithPrices); 109 | }); 110 | 111 | const getWonProducts = asyncHandler(async (req, res) => { 112 | const userId = req.user._id; 113 | 114 | const wonProducts = await Product.find({ soldTo: userId }).sort("-createdAt").populate("user"); 115 | 116 | const productsWithPrices = await Promise.all( 117 | wonProducts.map(async (product) => { 118 | const latestBid = await BiddingProduct.findOne({ product: product._id }).sort("-createdAt"); 119 | const biddingPrice = latestBid ? latestBid.price : product.price; 120 | return { 121 | ...product._doc, 122 | biddingPrice, // Adding the price field 123 | }; 124 | }) 125 | ); 126 | 127 | res.status(200).json(productsWithPrices); 128 | }); 129 | 130 | const getAllSoldProducts = asyncHandler(async (req, res) => { 131 | const product = await Product.find({ isSoldout: true }).sort("-createdAt").populate("user"); 132 | res.status(200).json(product); 133 | }); 134 | const getProductBySlug = asyncHandler(async (req, res) => { 135 | const { id } = req.params; 136 | const product = await Product.findById(id); 137 | if (!product) { 138 | res.status(404); 139 | throw new Error("Product not found"); 140 | } 141 | res.status(200).json(product); 142 | }); 143 | const deleteProduct = asyncHandler(async (req, res) => { 144 | const { id } = req.params; 145 | const product = await Product.findById(id); 146 | 147 | if (!product) { 148 | res.status(404); 149 | throw new Error("Product not found"); 150 | } 151 | if (product.user?.toString() !== req.user.id) { 152 | res.status(401); 153 | throw new Error("User not authorized"); 154 | } 155 | 156 | if (product.image && product.image.public_id) { 157 | try { 158 | await cloudinary.uploader.destroy(product.image.public_id); 159 | } catch (error) { 160 | console.error("Error deleting image from Cloudinary:", error); 161 | } 162 | } 163 | 164 | await Product.findByIdAndDelete(id); 165 | res.status(200).json({ message: "Product deleted." }); 166 | }); 167 | const updateProduct = asyncHandler(async (req, res) => { 168 | const { title, description, price, height, lengthpic, width, mediumused, weigth } = req.body; 169 | const { id } = req.params; 170 | const product = await Product.findById(id); 171 | 172 | if (!product) { 173 | res.status(404); 174 | throw new Error("Product not found"); 175 | } 176 | if (product.user.toString() !== req.user.id) { 177 | res.status(401); 178 | throw new Error("User not authorized"); 179 | } 180 | 181 | let fileData = {}; 182 | if (req.file) { 183 | let uploadedFile; 184 | try { 185 | uploadedFile = await cloudinary.uploader.upload(req.file.path, { 186 | folder: "Product-Images", 187 | resource_type: "image", 188 | }); 189 | } catch (error) { 190 | res.status(500); 191 | throw new Error("Image colud not be uploaded"); 192 | } 193 | 194 | if (product.image && product.image.public_id) { 195 | try { 196 | await cloudinary.uploader.destroy(product.image.public_id); 197 | } catch (error) { 198 | console.error("Error deleting previous image from Cloudinary:", error); 199 | } 200 | } 201 | //step 1 : 202 | fileData = { 203 | fileName: req.file.originalname, 204 | filePath: uploadedFile.secure_url, 205 | fileType: req.file.mimetype, 206 | public_id: uploadedFile.public_id, 207 | }; 208 | } 209 | 210 | const updatedProduct = await Product.findByIdAndUpdate( 211 | { _id: id }, 212 | { 213 | title, 214 | description, 215 | price, 216 | height, 217 | lengthpic, 218 | width, 219 | mediumused, 220 | weigth, 221 | image: Object.keys(fileData).length === 0 ? Product?.image : fileData, 222 | }, 223 | { 224 | new: true, 225 | runValidators: true, 226 | } 227 | ); 228 | res.status(200).json(updatedProduct); 229 | }); 230 | 231 | // for admin only users 232 | const verifyAndAddCommissionProductByAmdin = asyncHandler(async (req, res) => { 233 | const { commission } = req.body; 234 | const { id } = req.params; 235 | 236 | const product = await Product.findById(id); 237 | if (!product) { 238 | res.status(404); 239 | throw new Error("Product not found"); 240 | } 241 | 242 | product.isverify = true; 243 | product.commission = commission; 244 | 245 | await product.save(); 246 | 247 | res.status(200).json({ message: "Product verified successfully", data: product }); 248 | }); 249 | 250 | const getAllProductsByAmdin = asyncHandler(async (req, res) => { 251 | const products = await Product.find({}).sort("-createdAt").populate("user"); 252 | 253 | const productsWithPrices = await Promise.all( 254 | products.map(async (product) => { 255 | const latestBid = await BiddingProduct.findOne({ product: product._id }).sort("-createdAt"); 256 | const biddingPrice = latestBid ? latestBid.price : product.price; 257 | return { 258 | ...product._doc, 259 | biddingPrice, // Adding the price field 260 | }; 261 | }) 262 | ); 263 | 264 | res.status(200).json(productsWithPrices); 265 | }); 266 | 267 | // dot not it 268 | const deleteProductsByAmdin = asyncHandler(async (req, res) => { 269 | try { 270 | const { productIds } = req.body; 271 | 272 | const result = await Product.findOneAndDelete({ _id: productIds }); 273 | 274 | res.status(200).json({ message: `${result.deletedCount} products deleted successfully` }); 275 | } catch (error) { 276 | res.status(500).json({ error: error.message }); 277 | } 278 | }); 279 | 280 | module.exports = { 281 | createProduct, 282 | getAllProducts, 283 | getWonProducts, 284 | getProductBySlug, 285 | deleteProduct, 286 | updateProduct, 287 | verifyAndAddCommissionProductByAmdin, 288 | getAllProductsByAmdin, 289 | deleteProductsByAmdin, 290 | getAllSoldProducts, 291 | getAllProductsofUser, 292 | }; 293 | --------------------------------------------------------------------------------