Password scope added : GWM

This commit is contained in:
Gowtham M 2025-12-05 11:27:19 +05:30
parent 467e0c2634
commit 47f96ece22
4 changed files with 146 additions and 123 deletions

View File

@ -17,12 +17,12 @@ exports.login = async (req, res) => {
let userData = null;
// Try EstablishmentUser first
userData = await EstablishmentUser.findOne({ where: { email } });
userData = await EstablishmentUser.scope("withSensitive").findOne({ where: { email } });
if (userData) {
userRole = "EstablishmentUser";
} else {
// Try Admin user
userData = await User.findOne({ where: { email } });
userData = await User.scope("withSensitive").findOne({ where: { email } });
if (userData) {
userRole = "Admin";
}
@ -74,17 +74,16 @@ exports.login = async (req, res) => {
});
// Set token in HTTP-only cookie (IMPORTANT PART)
const isProd = process.env.NODE_ENV === "production";
res.cookie("auth_token", token, {
// httpOnly: true,
// secure: process.env.NODE_ENV === "production", // true in prod (HTTPS)
// sameSite: "lax", // or "strict" if suitable
// maxAge: 6 * 60 * 60 * 1000, // 6 hours in ms
httpOnly: true,
secure: true,
sameSite: "none",
maxAge: 6 * 60 * 60 * 1000, // 6 hours in ms
secure: isProd, // only true in production (HTTPS)
sameSite: isProd ? "none" : "lax", // 'none' requires HTTPS, so use 'lax' locally
maxAge: 6 * 60 * 60 * 1000, // 6 hours
});
// Optionally return minimal user info (WITHOUT password)
return res.status(200).json({
status: "success",

View File

@ -1,100 +1,120 @@
module.exports = (sequelize, DataTypes) => {
const EstablishmentUser = sequelize.define(
"establishment_users",
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
establishment_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
gender: {
type: DataTypes.STRING,
allowNull: true,
},
is_active: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
created_at: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
created_by: {
type: DataTypes.INTEGER,
allowNull: false,
},
updated_at: {
type: DataTypes.DATE,
allowNull: true,
},
updated_by: {
type: DataTypes.INTEGER,
allowNull: true,
},
last_login: {
type: DataTypes.DATE,
allowNull: true,
},
reset_otp: {
type: DataTypes.STRING,
allowNull: true,
},
reset_otp_expires_at: {
type: DataTypes.DATE,
allowNull: true,
const EstablishmentUser = sequelize.define(
"establishment_users",
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
establishment_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
gender: {
type: DataTypes.STRING,
allowNull: true,
},
is_active: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
created_at: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
created_by: {
type: DataTypes.INTEGER,
allowNull: false,
},
updated_at: {
type: DataTypes.DATE,
allowNull: true,
},
updated_by: {
type: DataTypes.INTEGER,
allowNull: true,
},
last_login: {
type: DataTypes.DATE,
allowNull: true,
},
reset_otp: {
type: DataTypes.STRING,
allowNull: true,
},
reset_otp_expires_at: {
type: DataTypes.DATE,
allowNull: true,
},
},
{
// ============================================================
// Model Options
// ============================================================
timestamps: false,
tableName: "establishment_users",
// 1. Hide sensitive fields by default
defaultScope: {
attributes: {
exclude: ["password", "reset_otp", "reset_otp_expires_at"],
},
},
{
timestamps: false,
tableName: "establishment_users",
// 2. Scope for login / sensitive queries
scopes: {
withSensitive: {
attributes: {
include: ["password", "reset_otp", "reset_otp_expires_at"],
},
},
},
// {
// // 1. EXCLUDE sensitive fields from all queries
// defaultScope: {
// attributes: { exclude: ["password", "reset_otp", "reset_otp_expires_at"] },
// },
}
);
// // -------------------------------------------------------------
// // 2. Special scope for login or OTP flows
// // Use: User.scope("withSensitive").findOne(...)
// // -------------------------------------------------------------
// scopes: {
// withSensitive: {
// attributes: {
// include: ["password", "reset_otp", "reset_otp_expires_at"],
// },
// },
// },
// }
);
EstablishmentUser.associate = (models) => {
EstablishmentUser.belongsTo(models.Establishment, {
foreignKey: 'establishment_id',
as: 'establishments',
});
};
return EstablishmentUser;
// 3. Remove sensitive fields from all API responses
EstablishmentUser.prototype.toJSON = function () {
const values = { ...this.get() };
delete values.password;
delete values.reset_otp;
delete values.reset_otp_expires_at;
return values;
};
// Relationships
EstablishmentUser.associate = (models) => {
EstablishmentUser.belongsTo(models.Establishment, {
foreignKey: "establishment_id",
as: "establishments",
});
};
return EstablishmentUser;
};

View File

@ -1,5 +1,7 @@
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define("admin_users", {
const User = sequelize.define(
"admin_users",
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
@ -35,24 +37,24 @@ module.exports = (sequelize, DataTypes) => {
defaultValue: true,
},
},
// {
// // 1. EXCLUDE sensitive fields from all queries
// defaultScope: {
// attributes: { exclude: ["password", "reset_otp", "reset_otp_expires_at"] },
// },
{
// 1. EXCLUDE sensitive fields from all queries
defaultScope: {
attributes: { exclude: ["password", "reset_otp", "reset_otp_expires_at"] },
},
// // -------------------------------------------------------------
// // 2. Special scope for login or OTP flows
// // Use: User.scope("withSensitive").findOne(...)
// // -------------------------------------------------------------
// scopes: {
// withSensitive: {
// attributes: {
// include: ["password", "reset_otp", "reset_otp_expires_at"],
// },
// },
// },
// }
// -------------------------------------------------------------
// 2. Special scope for login or OTP flows
// Use: User.scope("withSensitive").findOne(...)
// -------------------------------------------------------------
scopes: {
withSensitive: {
attributes: {
include: ["password", "reset_otp", "reset_otp_expires_at"],
},
},
},
}
);
return User;

View File

@ -3,11 +3,13 @@ const { NotificationTemplate } = require("../models"); // adjust path if needed
const logger = require("../services/logger");
require("dotenv").config();
const port = Number(process.env.MAIL_PORT);
const transporter = nodemailer.createTransport({
host: process.env.MAIL_HOST,
port: process.env.MAIL_PORT,
secure: false, // true for 465, false for 587
port,
secure: port === 465, // SSL
requireTLS: port === 587, // Enforce TLS for 587
auth: {
user: process.env.MAIL_USER,
pass: process.env.MAIL_PASS,