Added API send sign_in_verification_code
This commit is contained in:
parent
f37e0408d4
commit
38f53cd10f
@ -7,6 +7,7 @@ const EstablishmentProduct = db.EstablishmentProduct;
|
|||||||
const CityTown = db.CityTown;
|
const CityTown = db.CityTown;
|
||||||
const Emirate = db.Emirate;
|
const Emirate = db.Emirate;
|
||||||
const user = db.user;
|
const user = db.user;
|
||||||
|
const User = db.user;
|
||||||
const Product = db.Product;
|
const Product = db.Product;
|
||||||
const ExcelJS = require("exceljs");
|
const ExcelJS = require("exceljs");
|
||||||
const { Op, Sequelize } = require("sequelize");
|
const { Op, Sequelize } = require("sequelize");
|
||||||
@ -1049,6 +1050,81 @@ exports.forgotPasswordVerifyOTP = async (req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.requestOTPForLogin = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { registered_email } = req.body;
|
||||||
|
|
||||||
|
if (!registered_email) {
|
||||||
|
return res.status(400).json({
|
||||||
|
status: "failed",
|
||||||
|
message: "Email is required",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check which model contains the user
|
||||||
|
let loggingUser = await EstablishmentUser.findOne({
|
||||||
|
where: { email: registered_email }
|
||||||
|
});
|
||||||
|
let userModel = EstablishmentUser;
|
||||||
|
|
||||||
|
if (!loggingUser) {
|
||||||
|
loggingUser = await User.findOne({
|
||||||
|
where: { email: registered_email, is_active: true }
|
||||||
|
});
|
||||||
|
userModel = User;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loggingUser) {
|
||||||
|
logger.warn(`OTP requested for non-existing email: ${sanitizeForLog(registered_email)}`);
|
||||||
|
return res.status(404).json({
|
||||||
|
status: "failed",
|
||||||
|
message: "Invalid login request. Please check your email or register to continue.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secure OTP generation
|
||||||
|
const otp = crypto.randomInt(100000, 999999).toString();
|
||||||
|
|
||||||
|
// Hash OTP before storing
|
||||||
|
const hashedOtp = await bcrypt.hash(otp, 10);
|
||||||
|
|
||||||
|
// Store OTP in the correct model with WHERE clause
|
||||||
|
await userModel.update(
|
||||||
|
{
|
||||||
|
login_otp: hashedOtp,
|
||||||
|
login_otp_expires_at: new Date(Date.now() + 10 * 60 * 1000),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
where: { email: registered_email }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const placeHolderData = {
|
||||||
|
username: loggingUser.name,
|
||||||
|
verfication_code: otp,
|
||||||
|
support_email: process.env.SUPPORT_EMAIL,
|
||||||
|
support_phone: process.env.SUPPORT_PHONE
|
||||||
|
};
|
||||||
|
|
||||||
|
await sendEmailService(registered_email, "sign_in_verification_code", placeHolderData);
|
||||||
|
|
||||||
|
logger.info(`Login OTP email triggered for: ${sanitizeForLog(registered_email)}`);
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
status: "success",
|
||||||
|
message: "OTP sent successfully to your registered email",
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`OTP request failed: ${err.message}`);
|
||||||
|
logger.error(err.stack);
|
||||||
|
|
||||||
|
return res.status(500).json({
|
||||||
|
status: "failed",
|
||||||
|
message: "Internal Server Error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const GENERIC_ERROR_MSG =
|
const GENERIC_ERROR_MSG =
|
||||||
"Invalid data. Please check the instructions given and upload again.";
|
"Invalid data. Please check the instructions given and upload again.";
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,6 @@ const ConfigController = require("../controllers/config.controller");
|
|||||||
const dashboardController = require("../controllers/dashboard.controller");
|
const dashboardController = require("../controllers/dashboard.controller");
|
||||||
const notificationTemplateController = require("../controllers/notificationTemplate.controller");
|
const notificationTemplateController = require("../controllers/notificationTemplate.controller");
|
||||||
const quarterlyWindowsController = require("../controllers/quarterlyWindowsConfiguration.controller");
|
const quarterlyWindowsController = require("../controllers/quarterlyWindowsConfiguration.controller");
|
||||||
const calculationController = require("../controllers/calculation.controller");
|
|
||||||
const ManufacturingIpiController = require("../controllers/manufacturingIPI.controller")
|
const ManufacturingIpiController = require("../controllers/manufacturingIPI.controller")
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
@ -28,114 +27,6 @@ const upload = multer({ dest: UPLOAD_DIR });
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/calculate_base_year:
|
|
||||||
* post:
|
|
||||||
* summary: Base year calculation 2022
|
|
||||||
* tags: [IIP Calculation]
|
|
||||||
* security:
|
|
||||||
* - appSignature: []
|
|
||||||
* - CSRF: []
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: object
|
|
||||||
* required:
|
|
||||||
* - baseYear
|
|
||||||
* - forceRecalculate
|
|
||||||
* properties:
|
|
||||||
* baseYear:
|
|
||||||
* type: integer
|
|
||||||
* example: 2022
|
|
||||||
* forceRecalculate:
|
|
||||||
* type: string
|
|
||||||
* example: false
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Base year production calculated successfully
|
|
||||||
*/
|
|
||||||
|
|
||||||
router.post("/calculate_base_year",[] , calculationController.calculate_base_year);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/survey_auto_submit:
|
|
||||||
* post:
|
|
||||||
* summary: Auto survey submission for Quarter
|
|
||||||
* tags: [IIP Calculation]
|
|
||||||
* security:
|
|
||||||
* - appSignature: []
|
|
||||||
* - CSRF: []
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: object
|
|
||||||
* required:
|
|
||||||
* - year
|
|
||||||
* - quarter
|
|
||||||
* properties:
|
|
||||||
* year:
|
|
||||||
* type: integer
|
|
||||||
* example: 2025
|
|
||||||
* quarter:
|
|
||||||
* type: string
|
|
||||||
* enum: [Q1, Q2, Q3, Q4]
|
|
||||||
* example: Q2
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Auto survey completed successfully
|
|
||||||
*/
|
|
||||||
router.post("/survey_auto_submit",[] , calculationController.survey_auto_submit);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/calculate_quarter:
|
|
||||||
* post:
|
|
||||||
* summary: Calculate IPI for a selected year and quarter (Quarter → Month mapping)
|
|
||||||
* tags: [IIP Calculation]
|
|
||||||
* security:
|
|
||||||
* - appSignature: []
|
|
||||||
* - CSRF: []
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: object
|
|
||||||
* required:
|
|
||||||
* - year
|
|
||||||
* - quarter
|
|
||||||
* properties:
|
|
||||||
* year:
|
|
||||||
* type: integer
|
|
||||||
* example: 2025
|
|
||||||
* quarter:
|
|
||||||
* type: string
|
|
||||||
* enum: [Q1, Q2, Q3, Q4]
|
|
||||||
* example: Q2
|
|
||||||
* description: |
|
|
||||||
* Quarter to month mapping:
|
|
||||||
* - Q1 → Jan to Mar (1 - 3)
|
|
||||||
* - Q2 → Apr to Jun (4 - 6)
|
|
||||||
* - Q3 → Jul to Sep (7 - 9)
|
|
||||||
* - Q4 → Oct to Dec (10 - 12)
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Quarterly IPI calculation completed successfully
|
|
||||||
*/
|
|
||||||
|
|
||||||
router.post("/calculate_quarter",[] , calculationController.calculate_quarter);
|
|
||||||
|
|
||||||
|
|
||||||
router.get("/calculate_month",[] , calculationController.calculate_month);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* tags:
|
* tags:
|
||||||
@ -3158,6 +3049,35 @@ router.get("/manufacturing/getManufacturingIndex",[verifySignature, verifyToken]
|
|||||||
router.get("/manufacturing/getManufacturingMonthlyOverview", [verifySignature, verifyToken], ManufacturingIpiController.getManufacturingMonthlyOverviewByYearMonth);
|
router.get("/manufacturing/getManufacturingMonthlyOverview", [verifySignature, verifyToken], ManufacturingIpiController.getManufacturingMonthlyOverviewByYearMonth);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/login/request-otp:
|
||||||
|
* post:
|
||||||
|
* summary: Request OTP for login Admin or Establishment User
|
||||||
|
* tags: [Admin And Establishments User Auth]
|
||||||
|
* security:
|
||||||
|
* - appSignature: []
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* required:
|
||||||
|
* - registered_email
|
||||||
|
* properties:
|
||||||
|
* registered_email: { type: string, example: "contact@abcindustries.com" }
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: OTP sent successfully
|
||||||
|
* 400:
|
||||||
|
* description: Missing or invalid data
|
||||||
|
* 404:
|
||||||
|
* description: Establishment or user not found
|
||||||
|
* 500:
|
||||||
|
* description: Server error
|
||||||
|
*/
|
||||||
|
router.post("/login/request-otp",[verifySignature], establishmentController.requestOTPForLogin);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -241,6 +241,7 @@ app.use((req, res, next) => {
|
|||||||
"/api/forgot-password/request-otp",
|
"/api/forgot-password/request-otp",
|
||||||
"/api/forgot-password/verify-otp",
|
"/api/forgot-password/verify-otp",
|
||||||
"/api/csrf-token",
|
"/api/csrf-token",
|
||||||
|
"/api/login/request-otp"
|
||||||
];
|
];
|
||||||
|
|
||||||
if (csrfExcludedPaths.includes(req.path)) {
|
if (csrfExcludedPaths.includes(req.path)) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user