diff --git a/app/controllers/establishment.controller.js b/app/controllers/establishment.controller.js index 5e46a7d..ac015c9 100644 --- a/app/controllers/establishment.controller.js +++ b/app/controllers/establishment.controller.js @@ -968,7 +968,8 @@ exports.forgotPasswordVerifyOTP = async (req, res) => { if(user_type == 'establishment_user') { - const user = await EstablishmentUser.findOne({ where: { email: registered_email } }); + const user = await EstablishmentUser.scope("withSensitive").findOne({ where: { email: registered_email } }); + console.log(user); if (!user || !user.reset_otp) return res.status(404).json({ status: "failed", message: "verification code not found or invalid user" }); @@ -991,7 +992,7 @@ exports.forgotPasswordVerifyOTP = async (req, res) => { }else{ - const adminUser = await user.findOne({ where: { email: registered_email } }); + const adminUser = await user.scope("withSensitive").findOne({ where: { email: registered_email } }); if (!adminUser || !adminUser.reset_otp) return res.status(404).json({ status: "failed", message: "verification code not found or invalid user" }); diff --git a/app/routes/routes.js b/app/routes/routes.js index 8333f71..ce9c317 100644 --- a/app/routes/routes.js +++ b/app/routes/routes.js @@ -86,6 +86,11 @@ const upload = multer({ dest: UPLOAD_DIR }); * in: header * name: APP_SIGNATURE * description: "Signature key to identify authorized application" + * CSRF: + * type: apiKey + * in: header + * name: X-CSRF-Token + * description: "Signature key to identify authorized application" */ @@ -101,6 +106,7 @@ const upload = multer({ dest: UPLOAD_DIR }); * tags: [Admin And Establishments User Auth] * security: * - appSignature: [] + * - CSRF: [] * requestBody: * required: true * content: @@ -140,6 +146,7 @@ router.post("/auth/admin_register",[verifySignature], authController.register); * tags: [Admin And Establishments User Auth] * security: * - appSignature: [] + * - CSRF: [] * requestBody: * required: true * content: @@ -174,6 +181,7 @@ router.post("/auth/login",[verifySignature], authController.login); * tags: [Admin And Establishments User Auth] * security: * - appSignature: [] + * - CSRF: [] */ router.get("/auth/logout",[verifySignature], authController.logout); @@ -215,6 +223,7 @@ router.get("/auth/logout",[verifySignature], authController.logout); * tags: [Admin Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * responses: * 201: @@ -234,6 +243,7 @@ router.get("/admin_users", [verifySignature , verifyToken], adminUserController. * tags: [Admin Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -260,6 +270,7 @@ router.get("/admin_users/:id", [verifySignature, verifyToken], adminUserControll * tags: [Admin Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -291,6 +302,7 @@ router.post("/admin_users",[verifySignature, verifyToken], adminUserController.c * tags: [Admin Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -327,6 +339,7 @@ router.put("/admin_users/:id",[verifySignature, verifyToken], adminUserControlle * tags: [Admin Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -355,6 +368,7 @@ router.delete("/admin_users/:id",[verifySignature, verifyToken], adminUserContro * tags: [Admin Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -419,6 +433,7 @@ router.get("/testEmail", establishmentController.testEmail); * tags: [Establishments] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -513,6 +528,7 @@ router.post("/establishments",[verifySignature, verifyToken], establishmentContr * tags: [Establishments] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: query @@ -567,6 +583,7 @@ router.get("/establishments",[verifySignature, verifyToken], establishmentContro * tags: [Establishments] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -591,6 +608,7 @@ router.get("/establishments/:id",[verifySignature, verifyToken], establishmentCo * tags: [Establishments] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -675,6 +693,7 @@ router.put("/establishments/:id",[verifySignature, verifyToken], establishmentCo * tags: [Establishments] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -701,6 +720,7 @@ router.delete("/establishments/:id",[verifySignature, verifyToken], establishmen * tags: [Establishments] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -745,6 +765,7 @@ router.post("/establishments/uploadCSV",[verifySignature, verifyToken, upload.si * tags: [Establishment Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -794,6 +815,7 @@ router.post("/establishment-users",[verifySignature, verifyToken], establishment * tags: [Establishment Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: query @@ -817,6 +839,7 @@ router.get("/establishment-users",[verifySignature, verifyToken], establishmentU * tags: [Establishment Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -841,6 +864,7 @@ router.get("/establishment-users/:id",[verifySignature, verifyToken], establishm * tags: [Establishment Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -938,6 +962,7 @@ router.put("/establishment-users/:id/change-password",[verifySignature, verifyTo * tags: [Establishment Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -962,6 +987,7 @@ router.delete("/establishment-users/:id",[verifySignature, verifyToken], establi * tags: [Establishment Users] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -1003,6 +1029,7 @@ router.post("/trigger-establishment-users-welcome-email",[verifySignature, verif * tags: [Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -1041,6 +1068,7 @@ router.post("/products",[verifySignature, verifyToken], productController.create * tags: [Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * responses: * 200: @@ -1056,6 +1084,7 @@ router.get("/products",[verifySignature, verifyToken], productController.getAllP * tags: [Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1079,6 +1108,7 @@ router.get("/products/:id", [verifySignature, verifyToken],productController.get * tags: [Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1123,6 +1153,7 @@ router.put("/products/:id",[verifySignature, verifyToken], productController.upd * tags: [Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1147,6 +1178,7 @@ router.delete("/products/:id",[verifySignature, verifyToken], productController. * tags: [Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -1178,6 +1210,7 @@ router.post("/products/uploadCSV",[ verifySignature, verifyToken, upload.single( * tags: [Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * responses: * 200: @@ -1218,6 +1251,7 @@ router.get("/download-sample-product-upload-file",[verifySignature, verifyToken] * tags: [Establishment Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -1259,6 +1293,7 @@ router.post("/establishment-products",[verifySignature, verifyToken], establishm * tags: [Establishment Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: query @@ -1285,6 +1320,7 @@ router.get("/establishment-products",[verifySignature, verifyToken], establishme * tags: [Establishment Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1311,6 +1347,7 @@ router.get("/establishment-products/:id",[verifySignature, verifyToken], establi * tags: [Establishment Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1358,6 +1395,7 @@ router.put("/establishment-products/:id",[verifySignature, verifyToken], establi * tags: [Establishment Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1400,6 +1438,7 @@ router.delete("/establishment-products/:id",[verifySignature, verifyToken], esta * tags: [Variation Reason Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -1429,6 +1468,7 @@ router.post("/variation_reasons",[verifySignature, verifyToken], variationReason * tags: [Variation Reason Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * responses: * 200: @@ -1444,6 +1484,7 @@ router.get("/variation_reasons",[verifySignature, verifyToken], variationReasonM * tags: [Variation Reason Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1468,6 +1509,7 @@ router.get("/variation_reasons/:id",[verifySignature, verifyToken], variationRea * tags: [Variation Reason Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1508,6 +1550,7 @@ router.put("/variation_reasons/:id",[verifySignature, verifyToken], variationRea * tags: [Variation Reason Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1547,6 +1590,7 @@ router.delete("/variation_reasons/:id",[verifySignature, verifyToken], variation * tags: [Zero Target Reasons] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * responses: * 200: @@ -1562,6 +1606,7 @@ router.get("/zero_target_reason/",[verifySignature, verifyToken], zeroTargetReas * tags: [Zero Target Reasons] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -1583,6 +1628,7 @@ router.get("/zero_target_reason/:id",[verifySignature, verifyToken], zeroTargetR * tags: [Zero Target Reasons] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -1609,6 +1655,7 @@ router.post("/zero_target_reason/",[verifySignature, verifyToken], zeroTargetRea * tags: [Zero Target Reasons] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -1639,6 +1686,7 @@ router.put("/zero_target_reason/:id",[verifySignature, verifyToken], zeroTargetR * tags: [Zero Target Reasons] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -1669,6 +1717,7 @@ router.delete("/zero_target_reason/:id",[verifySignature, verifyToken], zeroTarg * tags: [Unit Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * responses: * 200: @@ -1684,6 +1733,7 @@ router.get("/unit_master",[verifySignature, verifyToken], unitMasterController.g * tags: [Unit Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1705,6 +1755,7 @@ router.get("/unit_master/:id",[verifySignature, verifyToken], unitMasterControll * tags: [Unit Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -1732,6 +1783,7 @@ router.post("/unit_master",[verifySignature, verifyToken], unitMasterController. * tags: [Unit Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1767,6 +1819,7 @@ router.put("/unit_master/:id",[verifySignature, verifyToken], unitMasterControll * tags: [Unit Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: path @@ -1789,6 +1842,7 @@ router.delete("/unit_master/:id",[verifySignature, verifyToken], unitMasterContr * tags: [Unit Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -1830,6 +1884,7 @@ router.post("/unit_master/uploadCSV",[ verifySignature, verifyToken, upload.sing * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -1899,6 +1954,7 @@ router.post("/submissions",[verifySignature, verifyToken], submissionController. * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -1973,6 +2029,7 @@ router.put("/submissions/:id",[verifySignature, verifyToken], submissionControll * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: establishment_id @@ -1992,6 +2049,7 @@ router.get("/submissions/history/:establishment_id",[verifySignature, verifyToke * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: query @@ -2038,6 +2096,7 @@ router.get("/submissions",[verifySignature, verifyToken], submissionController.s * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -2081,6 +2140,7 @@ router.get("/submissions/view/:id",[verifySignature, verifyToken], submissionCon * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -2109,6 +2169,7 @@ router.put("/submissionEditRequest/:id",[verifySignature, verifyToken], submissi * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -2139,6 +2200,7 @@ router.put("/enableOrDisableSubmissionEditAccess/:id",[verifySignature, verifyTo * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -2175,6 +2237,7 @@ router.put("/approveOrRejectSubmission/:id",[verifySignature, verifyToken], subm * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -2199,6 +2262,7 @@ router.post("/getQuarterPeriods",[verifySignature, verifyToken], submissionContr * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: query @@ -2235,6 +2299,7 @@ router.get("/submissions/getPreviousForecastData",[verifySignature, verifyToken] * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: query @@ -2272,6 +2337,7 @@ router.get("/submissions/getBeforePreviousData",[verifySignature, verifyToken], * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: query @@ -2301,6 +2367,7 @@ router.get("/submissions/getProductSubmissionHistory",[verifySignature, verifyTo * tags: [Submissions] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: query @@ -2358,6 +2425,7 @@ router.get("/submission-audit-history",[verifySignature, verifyToken], submissi * tags: [Config] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -2415,6 +2483,7 @@ router.post("/submission_deadlines",[verifySignature, verifyToken], ConfigContro * tags: [Dashboard] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: query @@ -2446,6 +2515,7 @@ router.get("/establishment_dashboard",[verifySignature, verifyToken],dashboardCo * tags: [Dashboard] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: query @@ -2495,6 +2565,7 @@ router.get("/admin_dashboard",[verifySignature, verifyToken], dashboardControlle * tags: [Notification Templates] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * responses: * 200: @@ -2510,6 +2581,7 @@ router.get("/notification_templates",[verifySignature, verifyToken], notificatio * tags: [Notification Templates] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -2531,6 +2603,7 @@ router.get("/notification_templates/:id",[verifySignature, verifyToken], notific * tags: [Notification Templates] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -2574,6 +2647,7 @@ router.put("/notification_templates/:id",[verifySignature, verifyToken], notific * tags: [Quarterly Windows Configuration] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * requestBody: * required: true @@ -2603,6 +2677,7 @@ router.post("/quarterly_windows",[verifySignature, verifyToken], quarterlyWindow * tags: [Quarterly Windows Configuration] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * responses: * 200: @@ -2618,6 +2693,7 @@ router.get("/quarterly_windows",[verifySignature, verifyToken], quarterlyWindows * tags: [Quarterly Windows Configuration] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -2637,6 +2713,7 @@ router.get("/quarterly_windows/:id",[verifySignature, verifyToken], quarterlyWin * tags: [Quarterly Windows Configuration] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - name: id @@ -2679,6 +2756,7 @@ router.put("/quarterly_windows/:id",[verifySignature, verifyToken], quarterlyWin * tags: [Establishment Reset Requests] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] * responses: * 200: @@ -2697,6 +2775,7 @@ router.get("/password-reset-requests", establishmentController.getAllRequests); * tags: [Establishment Reset Requests] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] * requestBody: * required: true @@ -2748,6 +2827,8 @@ router.post("/password-reset-requests", establishmentController.createRequest); * post: * summary: Request OTP for establishment user pwd reset * tags: [Establishment Pwd Reset Requests] + * security: + * - CSRF: [] * requestBody: * required: true * content: @@ -2784,6 +2865,8 @@ router.post("/forgot-password/request-otp", establishmentController.forgotPasswo * post: * summary: Verify OTP and reset establishment user Pwd * tags: [Establishment Pwd Reset Requests] + * security: + * - CSRF: [] * requestBody: * required: true * content: @@ -2828,6 +2911,7 @@ router.post("/forgot-password/verify-otp", establishmentController.forgotPasswor * tags: [Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * responses: * 200: @@ -2845,6 +2929,7 @@ router.get("/emirates", [verifySignature, verifyToken], establishmentController. * tags: [Master] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * parameters: * - in: query @@ -2868,6 +2953,7 @@ router.get("/city-towns", [verifySignature, verifyToken], establishmentControlle * tags: [Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * responses: * 200: @@ -2892,6 +2978,7 @@ router.get("/establishment/download-sample-file",[verifySignature, verifyToken], * tags: [Products] * security: * - appSignature: [] + * - CSRF: [] * cookieAuth: [] # or bearerAuth: [] if you use Authorization header * responses: * 200: diff --git a/package-lock.json b/package-lock.json index 3f081dd..4823430 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "bcryptjs": "^3.0.2", "cookie-parser": "^1.4.7", "cors": "^2.8.5", + "csurf": "^1.11.0", "csv-parser": "^3.2.0", "dotenv": "^17.2.3", "exceljs": "^4.4.0", @@ -744,6 +745,91 @@ "node": ">= 10" } }, + "node_modules/csrf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", + "integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==", + "dependencies": { + "rndm": "1.2.0", + "tsscmp": "1.0.6", + "uid-safe": "2.1.5" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/csurf": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.11.0.tgz", + "integrity": "sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ==", + "deprecated": "This package is archived and no longer maintained. For support, visit https://github.com/expressjs/express/discussions", + "dependencies": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "csrf": "3.1.0", + "http-errors": "~1.7.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/csurf/node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/csurf/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/csurf/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/csurf/node_modules/http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/csurf/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/csurf/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/csurf/node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, "node_modules/csv-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.2.0.tgz", @@ -2317,6 +2403,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -2422,6 +2516,11 @@ "rimraf": "bin.js" } }, + "node_modules/rndm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==" + }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -2889,6 +2988,14 @@ "node": ">= 14.0.0" } }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "engines": { + "node": ">=0.6.x" + } + }, "node_modules/type-is": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", @@ -2907,6 +3014,17 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", diff --git a/package.json b/package.json index c5cb4f1..c3325a8 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "bcryptjs": "^3.0.2", "cookie-parser": "^1.4.7", "cors": "^2.8.5", + "csurf": "^1.11.0", "csv-parser": "^3.2.0", "dotenv": "^17.2.3", "exceljs": "^4.4.0", diff --git a/server.js b/server.js index b07fdf1..88443a4 100644 --- a/server.js +++ b/server.js @@ -9,8 +9,24 @@ const db = require("./app/models"); const path = require("path"); const cookieParser = require("cookie-parser"); const sanitizeInput = require("./app/utils/sanitizeInput"); +const verifySignature = require("./app/middleware/app.middleware"); +const authController = require("./app/controllers/auth.controller"); +const establishmentController = require("./app/controllers/establishment.controller"); require("dotenv").config(); - + +const csrf = require("csurf"); + +// cookie-based CSRF protection +const csrfProtection = csrf({ + cookie: { + key: "_csrf", + httpOnly: true, + secure: process.env.NODE_ENV === "production", + sameSite: "strict", + }, +}); + + const app = express(); // REQUIRED for HSTS when behind proxy (AWS ALB / Nginx / Cloudflare) @@ -135,7 +151,50 @@ app.use( // Routes -app.use("/api", routes); +/** + * -------------------- + * AUTH (NO CSRF) + * -------------------- + */ +app.post("api/auth/login",[verifySignature], authController.login); +app.post("api/forgot-password/request-otp",[verifySignature], establishmentController.forgotPasswordRequestOTP); +app.post("api/forgot-password/request-otp",[verifySignature], establishmentController.forgotPasswordRequestOTP); + +/** + * -------------------- + * CSRF TOKEN ENDPOINT + * -------------------- + */ +app.get("/api/csrf-token", csrfProtection, (req, res) => { + res.status(200).json({ + csrfToken: req.csrfToken(), + }); +}); + +/** + * -------------------- + * PROTECTED ROUTES (CSRF REQUIRED) + * -------------------- + */ +app.use("/api", csrfProtection, routes); +// app.use("/api", routes); + +/** + * -------------------- + * CSRF ERROR HANDLER + * -------------------- + */ +app.use((err, req, res, next) => { + if (err.code === "EBADCSRFTOKEN") { + return res.status(403).json({ + status: "failed", + message: "Invalid or missing CSRF token", + }); + } + next(err); +}); + + apis: [path.join(__dirname, "app/routes/*.js")], @@ -144,6 +203,9 @@ app.get("/api/test", (req, res) => { res.json({ status: "success", message: "Test API working fine 🚀" }); }); + + + //deployment route const deploymentController = require("./app/controllers/deployment.controller"); app.post("/deploy", deploymentController.deployment);