diff --git a/app/controllers/auth.controller.js b/app/controllers/auth.controller.js index 5ad086b..5088191 100644 --- a/app/controllers/auth.controller.js +++ b/app/controllers/auth.controller.js @@ -41,7 +41,7 @@ exports.login = async (req, res) => { // Check password const validPass = await bcrypt.compare(password, userData.password); if (!validPass) { - return res.status(401).json({ status: "failed", message: "Invalid password", data: "" }); + return res.status(401).json({ status: "failed", message: "Invalid password" }); } // Prepare token data @@ -115,62 +115,41 @@ exports.logout = (req, res) => { }); }; - // Register new user exports.register = async (req, res) => { try { const { name, email, password } = req.body; if (!name || !email || !password) - return res.status(400).send({'status':"failed",'message':"All fields required",'data': ""}); + return res.status(400).send({ + status: "error", + code: "MISSING_FIELDS", + message: "All fields are required", + data: "" + }); const existing = await User.findOne({ where: { email } }); - if (existing) res.status(400).send({'status':"failed",'message':"Email already used",'data': ""}); - + if (existing) { + return res.status(400).send({ + status: "error", + code: "EMAIL_IN_USE", + message: "Email already used", + data: "" + }); + } const hashedPassword = await bcrypt.hash(password, 10); const newUser = await User.create({ name, email, password: hashedPassword }); + return res.status(201).send({ + status: "ok", + code: "REGISTERED", + message: "User registered successfully", + data: newUser + }); - res.status(201).send({'status':"success",'message':"User registered successfully",'data': newUser }); } catch (err) { - res.status(500).send({'status':"failed",'message':err.message }); + return res.status(500).send({ + status: "error", + code: "SERVER_ERROR", + message: "An unexpected error occurred" + }); } }; - -// Login user -// exports.login = async (req, res) => { -// try { -// const { email, password } = req.body; - -// userRole = 'EstablishmentUser' -// userData = await EstablishmentUser.findOne({ where: { email, is_active : { [Op.or]: [true, 1] } } }); -// if (!userData) { -// userData = await User.findOne({ where: { email, is_active : { [Op.or]: [true, 1] } } }); -// userRole = 'Admin' -// if (!userData) res.status(404).send({'status':"failed",'message':"User not found",'data': ""}); -// } - - -// const validPass = await bcrypt.compare(password, userData.password); -// if (!validPass) res.status(401).send({'status':"failed",'message':"Invalid password",'data': ""}); - - -// if(userRole == 'Admin') -// { -// tokenData = { id: userData.id, email: userData.email , name: userData.name , role : userRole , last_login : userData.last_login } -// await User.update({ last_login : Date() }, { where: { id: userData.id } }); -// }else{ -// const establishment_data = await Establishment.findByPk(userData.establishment_id); -// tokenData = { id: userData.id, email: userData.email , name: userData.name , role : userRole , establishment_id: userData.establishment_id , establishment_data , last_login : userData.last_login } -// await EstablishmentUser.update({ last_login : Date(), updated_at: new Date() }, { where: { id: userData.id } }); -// } - -// const token = jwt.sign(tokenData, process.env.JWT_SECRET, { -// expiresIn: "6h", -// }); - -// res.status(200).send({'status':"success",'message':"Login successful",'data': token }); - -// } catch (err) { -// res.status(500).send({'status':"failed",'message':err.message }); -// } -// }; - diff --git a/app/controllers/establishment.controller.js b/app/controllers/establishment.controller.js index 1c7ed53..f0d9088 100644 --- a/app/controllers/establishment.controller.js +++ b/app/controllers/establishment.controller.js @@ -18,15 +18,16 @@ const csv = require("csv-parser"); const path = require("path"); const { version } = require("os"); const sequelize = db.sequelize; +const { sanitizeForLog } = require("../utils/sanitize"); exports.testEmail = async (req, res) => { placeHolderData = { contact_name : 'Gowtham', portal_url : process.env.FE_BASE_URL, - username : '--', - password : '--', - support_email : '--', - support_phone : '--', + username: 'test_user', + password: 'Test@123!', + support_email : process.env.SUPPORT_EMAIL, + support_phone : process.env.SUPPORT_PHONE, } await sendEmailService('gowthamceline46@gmail.com', 'establishment_user_creation_to_user', placeHolderData); @@ -186,15 +187,15 @@ exports.createEstablishment = async (req, res) => { //send email to user placeHolderData = { - contact_name : establishment_user.name, + contact_name : sanitizeForLog(establishment_user.name), portal_url : process.env.FE_BASE_URL, - username : establishment_user.email, + username : sanitizeForLog(establishment_user.email), password : establishment_user.password, support_email : process.env.SUPPORT_EMAIL, support_phone : process.env.SUPPORT_PHONE, } - await sendEmailService(establishment_user.email, 'establishment_user_creation_to_user', placeHolderData); + await sendEmailService(sanitizeForLog(establishment_user.email), 'establishment_user_creation_to_user', placeHolderData); // insert establishment_products // if (Array.isArray(establishment_products) && establishment_products.length > 0) { @@ -297,51 +298,6 @@ exports.createEstablishment = async (req, res) => { } }; -// Get all establishments -// exports.getAllEstablishments = async (req, res) => { -// try { - -// const data = await Establishment.findAll({ -// include: [ -// // { -// // model: EstablishmentUser, -// // as: "users", -// // attributes: ["id", "name", "email", "is_active"], -// // }, -// { -// model: CityTown, -// as: "establishment_city", -// attributes: ["name"], -// }, -// { -// model: Emirate, -// as: "establishment_emirate", -// attributes: ["name"], -// },{ -// model: CityTown, -// as: "corporate_city", -// attributes: ["name"], -// }, -// { -// model: Emirate, -// as: "corporate_emirate", -// attributes: ["name"], -// }, -// { -// model: user, -// as: "created_user", -// attributes: ["name"], -// } - -// ], -// }); - -// return res.status(200).send({'status':"success",'message':"Fetched successfully",'data': data }); - -// } catch (err) { -// return res.status(500).send({'status':"failed",'message':err.message }); -// } -// }; exports.getAllEstablishments = async (req, res) => { try { let { @@ -1026,7 +982,9 @@ exports.forgotPasswordRequestOTP = async (req, res) => { `
Dear ${adminUser.name},
Your OTP for password reset is ${otp}. It is valid for 10 minutes.
` ); } - logger.info(`OTP sent to ${registered_email}`); + + const safeEmail = sanitizeForLog(registered_email); + logger.info(`OTP sent email: ${safeEmail}`); return res.status(200).json({ status: "success", @@ -1100,7 +1058,8 @@ exports.forgotPasswordVerifyOTP = async (req, res) => { } - logger.info(`Password reset successful for user=${registered_email}`); + const safeEmail = sanitizeForLog(registered_email); + logger.info(`Password reset successful for user: ${safeEmail}`); return res.status(200).json({ status: "success", diff --git a/app/controllers/establishment_user.controller.js b/app/controllers/establishment_user.controller.js index 630a3fc..4e64c82 100644 --- a/app/controllers/establishment_user.controller.js +++ b/app/controllers/establishment_user.controller.js @@ -3,6 +3,7 @@ const bcrypt = require("bcryptjs"); const EstablishmentUser = db.EstablishmentUser; const { sendEmailService } = require("../services/email.service"); +const { sanitizeForLog } = require("../utils/sanitize"); // Create User exports.createUser = async (req, res) => { @@ -11,10 +12,25 @@ exports.createUser = async (req, res) => { const { establishment_id, name, email, password , gender} = req.body; const hashed = await bcrypt.hash(password, 10); - // Check if establishment user already exists - const existingEstablishmentUser = await EstablishmentUser.findOne({where: { email }, }); - if (existingEstablishmentUser) { - return res.status(400).send({status: "failed",message: "Email already exists", }); + email = sanitizeForLog(email || ""); + name = sanitizeForLog(name || ""); + gender = sanitizeForLog(gender || ""); + + if (!establishment_id || !email) { + return res.status(400).send({ + status: "error", + code: "MISSING_FIELDS", + message: "establishment_id and email are required" + }); + } + + const existing = await EstablishmentUser.findOne({ where: { email, is_active: true } }); + if (existing) { + return res.status(400).send({ + status: "error", + code: "EMAIL_EXISTS", + message: "Email already exists" + }); } const user = await EstablishmentUser.create({ @@ -38,10 +54,10 @@ exports.createUser = async (req, res) => { } await sendEmailService(email, 'establishment_user_creation_to_user', placeHolderData); - return res.status(201).send({'status':"success",'message':"Creation successful",'data': user }); + return res.status(201).send({'status':"ok", 'message':"Creation successful",'data': user }); } catch (err) { - return res.status(500).send({'status':"failed",'message':err.message }); + return res.status(500).send({'status':"error",'message':err.message }); } }; @@ -108,23 +124,39 @@ exports.changeUserPassword = async (req, res) => { // Validate inputs if (!old_password || !new_password || !confirm_password) { - return res.status(400).send({ status: "failed", message: "All password fields are required" }); + return res.status(400).send({ + status: "error", + code: "MISSING_FIELDS", + message: "All password fields are required" + }); } if (new_password !== confirm_password) { - return res.status(400).send({ status: "failed", message: "New password and confirm password do not match" }); + return res.status(400).send({ + status: "error", + code: "PASSWORD_MISMATCH", + message: "New password and confirm password do not match" + }); } // Find user const user = await EstablishmentUser.findByPk(userId); if (!user) { - return res.status(404).send({ status: "failed", message: "User not found" }); + return res.status(404).send({ + status: "error", + code: "USER_NOT_FOUND", + message: "User not found" + }); } // Verify old password const isMatch = await bcrypt.compare(old_password, user.password); if (!isMatch) { - return res.status(400).send({ status: "failed", message: "Old password is incorrect" }); + return res.status(401).send({ + status: "error", + code: "OLD_PASSWORD_INCORRECT", + message: "Old password is incorrect" + }); } // Hash and update new password @@ -134,10 +166,18 @@ exports.changeUserPassword = async (req, res) => { { where: { id: userId } } ); - return res.status(200).send({status: "success", message: "Password updated successfully",}); - + return res.status(200).send({ + status: "ok", + code: "PASSWORD_UPDATED", + message: "Password updated successfully" + }); + } catch (err) { - return res.status(500).send({ status: "failed", message: err.message }); + return res.status(500).send({ + status: "error", + code: "SERVER_ERROR", + message: "An unexpected error occurred" + }); } }; diff --git a/app/controllers/submission.controller.js b/app/controllers/submission.controller.js index 59eea7a..7ccc24f 100644 --- a/app/controllers/submission.controller.js +++ b/app/controllers/submission.controller.js @@ -18,7 +18,7 @@ const { Sequelize } = require("sequelize"); const { sendEmail } = require("../services/email.service"); const { sendEmailService } = require("../services/email.service"); const { getQuarterPeriods } = require("../services/quarterService"); - +const { sanitizeForLog } = require("../utils/sanitize"); exports.createSubmission = async (req, res) => { @@ -741,24 +741,30 @@ exports.approveOrRejectSubmission = async (req, res) => { try { const { id } = req.params; - approve_reject_status = req.body.approve_reject_status; - reject_reason = req.body.reject_reason; - approve_or_reject_by = req.body.approve_or_reject_by || req.user.id; + const approve_reject_status = sanitizeForLog(req.body.approve_reject_status); + const reject_reason = sanitizeForLog(req.body.reject_reason || ""); + const approve_or_reject_by = sanitizeForLog(req.body.approve_or_reject_by || req.user.id); - if(approve_reject_status == 1) - { - statusString = 'Approved'; - }else{ - statusString = 'Rejected'; + if (![1, "1", 0, "0"].includes(approve_reject_status)) { + return res.status(400).json({ + status: "failed", + message: "approve_reject_status must be 1 or 0" + }); } - // Check submission exists + const statusString = approve_reject_status == 1 ? "Approved" : "Rejected"; const submission = await Submission.findByPk(id); if (!submission) return res.status(404).json({ status: "failed", message: "Submission not found" }); - // Update submission main data - const result = await submission.update({ approve_reject_status : approve_reject_status , status : statusString, reject_reason, approve_or_reject_by: approve_or_reject_by, updated_by: req.user.id, updated_at: new Date() }); + const result = await submission.update({ + approve_reject_status, + status: statusString, + reject_reason, + approve_or_reject_by, + updated_by: req.user.id, + updated_at: new Date() + }); //send email to establishment user @@ -769,54 +775,42 @@ exports.approveOrRejectSubmission = async (req, res) => { { for await (const userObj of EstablishmentUserData) { - placeHolderData = { - user_name : userObj.name, - portal_url : process.env.FE_BASE_URL, - quarter : result['quarter'], - year : result['year'], - establishment_name : EstablishmentData['factory_name'], - submission_date : result['created_at'], - rejection_reason : result['reject_reason'], - support_email : process.env.SUPPORT_EMAIL, - support_phone : process.env.SUPPORT_PHONE, - } + placeHolderData = { + user_name: sanitizeForLog(userObj.name), + portal_url : process.env.FE_BASE_URL, + quarter : result['quarter'], + year : result['year'], + establishment_name : EstablishmentData['factory_name'], + submission_date : result['created_at'], + rejection_reason : result['reject_reason'], + support_email : process.env.SUPPORT_EMAIL, + support_phone : process.env.SUPPORT_PHONE, + }; - await sendEmailService(userObj.email, 'submission_approved_mail_to_establishment_user', placeHolderData); - } - - }else{ - - for await (const userObj of EstablishmentUserData) - { - placeHolderData = { - user_name : userObj.name, - portal_url : process.env.FE_BASE_URL, - quarter : result['quarter'], - year : result['year'], - establishment_name : EstablishmentData['factory_name'], - submission_date : result['created_at'], - rejection_reason : result['reject_reason'], - support_email : process.env.SUPPORT_EMAIL, - support_phone : process.env.SUPPORT_PHONE, - } + const template = approve_reject_status == 1 + ? "submission_approved_mail_to_establishment_user" + : "submission_rejected_mail_to_establishment_user"; - await sendEmailService(userObj.email, 'submission_rejected_mail_to_establishment_user', placeHolderData); - } + await sendEmailService( + sanitizeForLog(userObj.email), + template, + placeHolderData + ); } - - - res.status(200).json({ + } + return res.status(200).json({ status: "success", message: "Submission edit access updated", data: result, }); - } catch (err) { console.error(err); - res.status(500).json({ status: "failed", message: err.message }); + res.status(500).json({ status: "failed", message: sanitizeForLog(err.message) }); } + }; + exports.getQuarterPeriods = async (req, res) => { try { const { current_year, current_quarter } = req.body; diff --git a/app/controllers/user.controller.js b/app/controllers/user.controller.js index 2c69c2f..a6e8c0c 100644 --- a/app/controllers/user.controller.js +++ b/app/controllers/user.controller.js @@ -15,9 +15,9 @@ exports.createUser = async (req, res) => { const user = await User.create({ name, email, password: hashedPassword }); - logger.info(`User created: ${email}`); + logger.info("User created successfully"); - res.status(201).send({'status':"success",'message':"created successfully" }); + res.status(201).send({'status':"success",'message':"User created successfully" }); } catch (err) { logger.error(err.message); diff --git a/app/routes/routes.js b/app/routes/routes.js index c9bd875..1e4ff50 100644 --- a/app/routes/routes.js +++ b/app/routes/routes.js @@ -131,7 +131,7 @@ const upload = multer({ dest: uploadDir }); * example: john@example.com * password: * type: string - * example: secret123 + * example: "