changed model
This commit is contained in:
parent
e5bca1f2e9
commit
2d712682cf
@ -1051,157 +1051,156 @@ exports.forgotPasswordVerifyOTP = async (req, res) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
exports.requestOTPForLogin = async (req, res) => {
|
exports.requestOTPForLogin = async (req, res) => {
|
||||||
try {
|
// try {
|
||||||
const { registered_email } = req.body;
|
// const { registered_email } = req.body;
|
||||||
|
|
||||||
if (!registered_email) {
|
// if (!registered_email) {
|
||||||
return res.status(400).json({
|
// return res.status(400).json({
|
||||||
status: "failed",
|
// status: "failed",
|
||||||
message: "Email is required",
|
// message: "Email is required",
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Check which model contains the user
|
// // Check which model contains the user
|
||||||
let loggingUser = await EstablishmentUser.findOne({
|
// let loggingUser = await EstablishmentUser.findOne({
|
||||||
where: { email: registered_email }
|
// where: { email: registered_email }
|
||||||
});
|
// });
|
||||||
let userModel = EstablishmentUser;
|
// let userModel = EstablishmentUser;
|
||||||
|
|
||||||
if (!loggingUser) {
|
// if (!loggingUser) {
|
||||||
loggingUser = await User.findOne({
|
// loggingUser = await User.findOne({
|
||||||
where: { email: registered_email, is_active: true }
|
// where: { email: registered_email, is_active: true }
|
||||||
});
|
// });
|
||||||
userModel = User;
|
// userModel = User;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!loggingUser) {
|
// if (!loggingUser) {
|
||||||
logger.warn(`OTP requested for non-existing email: ${sanitizeForLog(registered_email)}`);
|
// logger.warn(`OTP requested for non-existing email: ${sanitizeForLog(registered_email)}`);
|
||||||
return res.status(404).json({
|
// return res.status(404).json({
|
||||||
status: "failed",
|
// status: "failed",
|
||||||
message: "Invalid login request. Please check your email or register to continue.",
|
// message: "Invalid login request. Please check your email or register to continue.",
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Secure OTP generation
|
// // Secure OTP generation
|
||||||
const otp = crypto.randomInt(100000, 999999).toString();
|
// const otp = crypto.randomInt(100000, 999999).toString();
|
||||||
|
|
||||||
// Hash OTP before storing
|
// // Hash OTP before storing
|
||||||
const hashedOtp = await bcrypt.hash(otp, 10);
|
// const hashedOtp = await bcrypt.hash(otp, 10);
|
||||||
|
|
||||||
// Store OTP in the correct model with WHERE clause
|
// // Store OTP in the correct model with WHERE clause
|
||||||
await userModel.update(
|
// await userModel.update(
|
||||||
{
|
// {
|
||||||
login_otp: hashedOtp,
|
// login_otp: hashedOtp,
|
||||||
login_otp_expires_at: new Date(Date.now() + 10 * 60 * 1000),
|
// login_otp_expires_at: new Date(Date.now() + 10 * 60 * 1000),
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
where: { email: registered_email }
|
// where: { email: registered_email }
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
const placeHolderData = {
|
// const placeHolderData = {
|
||||||
username: loggingUser.name,
|
// username: loggingUser.name,
|
||||||
verfication_code: otp,
|
// verfication_code: otp,
|
||||||
support_email: process.env.SUPPORT_EMAIL,
|
// support_email: process.env.SUPPORT_EMAIL,
|
||||||
support_phone: process.env.SUPPORT_PHONE
|
// support_phone: process.env.SUPPORT_PHONE
|
||||||
};
|
// };
|
||||||
|
|
||||||
await sendEmailService(registered_email, "sign_in_verification_code", placeHolderData);
|
// await sendEmailService(registered_email, "sign_in_verification_code", placeHolderData);
|
||||||
|
|
||||||
logger.info(`Login OTP email triggered for: ${sanitizeForLog(registered_email)}`);
|
// logger.info(`Login OTP email triggered for: ${sanitizeForLog(registered_email)}`);
|
||||||
|
|
||||||
return res.status(200).json({
|
// return res.status(200).json({
|
||||||
status: "success",
|
// status: "success",
|
||||||
message: "OTP sent successfully to your registered email",
|
// message: "OTP sent successfully to your registered email",
|
||||||
});
|
// });
|
||||||
|
|
||||||
} catch (err) {
|
// } catch (err) {
|
||||||
logger.error(`OTP request failed: ${err.message}`);
|
// logger.error(`OTP request failed: ${err.message}`);
|
||||||
logger.error(err.stack);
|
// logger.error(err.stack);
|
||||||
|
|
||||||
return res.status(500).json({
|
// return res.status(500).json({
|
||||||
status: "failed",
|
// status: "failed",
|
||||||
message: "Internal Server Error",
|
// message: "Internal Server Error",
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.verifyOTPForLogin = async (req, res) => {
|
exports.verifyOTPForLogin = async (req, res) => {
|
||||||
try {
|
// try {
|
||||||
const { registered_email, otp } = req.body;
|
// const { registered_email, otp } = req.body;
|
||||||
|
|
||||||
|
// if (!registered_email || !otp) {
|
||||||
|
// return res.status(400).json({
|
||||||
|
// status: "failed",
|
||||||
|
// message: "Email and OTP are required"
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
// Validation
|
// // Find user from either model
|
||||||
if (!registered_email || !otp) {
|
// let user = await EstablishmentUser.scope("withSensitive").findOne({
|
||||||
return res.status(400).json({
|
// where: { email: registered_email }
|
||||||
status: "failed",
|
// });
|
||||||
message: "Email and OTP are required"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find user from either model
|
// if (!user) {
|
||||||
let user = await EstablishmentUser.scope("withSensitive").findOne({
|
// user = await User.scope("withSensitive").findOne({
|
||||||
where: { email: registered_email }
|
// where: { email: registered_email, is_active: true }
|
||||||
});
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
if (!user) {
|
// // User validation
|
||||||
user = await User.scope("withSensitive").findOne({
|
// if (!user) {
|
||||||
where: { email: registered_email, is_active: true }
|
// return res.status(404).json({
|
||||||
});
|
// status: "failed",
|
||||||
}
|
// message: "User not found"
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
// User validation
|
// if (!user.login_otp) {
|
||||||
if (!user) {
|
// return res.status(404).json({
|
||||||
return res.status(404).json({
|
// status: "failed",
|
||||||
status: "failed",
|
// message: "Verification code not found or invalid user"
|
||||||
message: "User not found"
|
// });
|
||||||
});
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.login_otp) {
|
// // Check OTP expiry
|
||||||
return res.status(404).json({
|
// if (new Date() > new Date(user.login_otp_expires_at)) {
|
||||||
status: "failed",
|
// return res.status(400).json({
|
||||||
message: "Verification code not found or invalid user"
|
// status: "failed",
|
||||||
});
|
// message: "Verification code has expired. Please request a new one"
|
||||||
}
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
// Check OTP expiry
|
// // Verify OTP
|
||||||
if (new Date() > new Date(user.login_otp_expires_at)) {
|
// const isOtpValid = await bcrypt.compare(otp, user.login_otp);
|
||||||
return res.status(400).json({
|
// if (!isOtpValid) {
|
||||||
status: "failed",
|
// return res.status(400).json({
|
||||||
message: "Verification code has expired. Please request a new one"
|
// status: "failed",
|
||||||
});
|
// message: "Invalid verification code"
|
||||||
}
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
// Verify OTP
|
// // Clear OTP after successful verification
|
||||||
const isOtpValid = await bcrypt.compare(otp, user.login_otp);
|
// await user.update({
|
||||||
if (!isOtpValid) {
|
// login_otp: null,
|
||||||
return res.status(400).json({
|
// login_otp_expires_at: null,
|
||||||
status: "failed",
|
// });
|
||||||
message: "Invalid verification code"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear OTP after successful verification
|
// const safeEmail = sanitizeForLog(registered_email);
|
||||||
await user.update({
|
// logger.info(`OTP verification successful for user: ${safeEmail}`);
|
||||||
login_otp: null,
|
|
||||||
login_otp_expires_at: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
const safeEmail = sanitizeForLog(registered_email);
|
// return res.status(200).json({
|
||||||
logger.info(`OTP verification successful for user: ${safeEmail}`);
|
// status: "success",
|
||||||
|
// message: "Email verified successfully!",
|
||||||
|
// });
|
||||||
|
|
||||||
return res.status(200).json({
|
// } catch (err) {
|
||||||
status: "success",
|
// logger.error(`OTP verification error: ${err.message}`);
|
||||||
message: "Email verified successfully!",
|
// logger.error(`Stack trace: ${err.stack}`);
|
||||||
});
|
// return res.status(500).json({
|
||||||
|
// status: "failed",
|
||||||
} catch (err) {
|
// message: "Internal server error"
|
||||||
logger.error(`OTP verification error: ${err.message}`);
|
// });
|
||||||
logger.error(`Stack trace: ${err.stack}`);
|
// }
|
||||||
return res.status(500).json({
|
|
||||||
status: "failed",
|
|
||||||
message: "Internal server error"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const GENERIC_ERROR_MSG =
|
const GENERIC_ERROR_MSG =
|
||||||
|
|||||||
@ -74,64 +74,41 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
allowNull: true,
|
allowNull: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
login_otp: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
login_otp_expires_at: {
|
|
||||||
type: DataTypes.DATE,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
|
// ============================================================
|
||||||
|
// Model Options
|
||||||
|
// ============================================================
|
||||||
timestamps: false,
|
timestamps: false,
|
||||||
tableName: "establishment_users",
|
tableName: "establishment_users",
|
||||||
|
|
||||||
// Hide sensitive fields by default
|
// 1. Hide sensitive fields by default
|
||||||
defaultScope: {
|
defaultScope: {
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: [
|
exclude: ["password", "reset_otp", "reset_otp_expires_at"],
|
||||||
"password",
|
|
||||||
"reset_otp",
|
|
||||||
"reset_otp_expires_at",
|
|
||||||
"login_otp",
|
|
||||||
"login_otp_expires_at",
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Scope for login & sensitive operations
|
// 2. Scope for login / sensitive queries
|
||||||
scopes: {
|
scopes: {
|
||||||
withSensitive: {
|
withSensitive: {
|
||||||
attributes: {
|
attributes: {
|
||||||
include: [
|
include: ["password", "reset_otp", "reset_otp_expires_at"],
|
||||||
"password",
|
|
||||||
"reset_otp",
|
|
||||||
"reset_otp_expires_at",
|
|
||||||
"login_otp",
|
|
||||||
"login_otp_expires_at",
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 3. Remove sensitive fields from all API responses
|
||||||
EstablishmentUser.prototype.toJSON = function () {
|
EstablishmentUser.prototype.toJSON = function () {
|
||||||
const values = { ...this.get() };
|
const values = { ...this.get() };
|
||||||
delete values.password;
|
delete values.password;
|
||||||
delete values.reset_otp;
|
delete values.reset_otp;
|
||||||
delete values.reset_otp_expires_at;
|
delete values.reset_otp_expires_at;
|
||||||
delete values.login_otp;
|
|
||||||
delete values.login_otp_expires_at;
|
|
||||||
return values;
|
return values;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ====================================================
|
// Relationships
|
||||||
// Associations
|
|
||||||
// ====================================================
|
|
||||||
EstablishmentUser.associate = (models) => {
|
EstablishmentUser.associate = (models) => {
|
||||||
EstablishmentUser.belongsTo(models.Establishment, {
|
EstablishmentUser.belongsTo(models.Establishment, {
|
||||||
foreignKey: "establishment_id",
|
foreignKey: "establishment_id",
|
||||||
@ -140,4 +117,4 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return EstablishmentUser;
|
return EstablishmentUser;
|
||||||
};
|
};
|
||||||
@ -32,32 +32,15 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
type: DataTypes.DATE,
|
type: DataTypes.DATE,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
},
|
},
|
||||||
login_otp: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
login_otp_expires_at: {
|
|
||||||
type: DataTypes.DATE,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
is_active: {
|
is_active: {
|
||||||
type: DataTypes.BOOLEAN,
|
type: DataTypes.BOOLEAN,
|
||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultScope: {
|
// 1. EXCLUDE sensitive fields from all queries
|
||||||
attributes: {
|
defaultScope: {
|
||||||
exclude: [
|
attributes: { exclude: ["password", "reset_otp", "reset_otp_expires_at"] },
|
||||||
"password",
|
|
||||||
"reset_otp",
|
|
||||||
"reset_otp_expires_at",
|
|
||||||
"login_otp",
|
|
||||||
"login_otp_expires_at",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
@ -67,18 +50,12 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
scopes: {
|
scopes: {
|
||||||
withSensitive: {
|
withSensitive: {
|
||||||
attributes: {
|
attributes: {
|
||||||
include: [
|
include: ["password", "reset_otp", "reset_otp_expires_at"],
|
||||||
"password",
|
|
||||||
"reset_otp",
|
|
||||||
"reset_otp_expires_at",
|
|
||||||
"login_otp",
|
|
||||||
"login_otp_expires_at",
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return User;
|
return User;
|
||||||
};
|
};
|
||||||
Loading…
Reference in New Issue
Block a user