Merge branch 'master' of bitbucket.org:jubilian/fcsc_ipi_backend

This commit is contained in:
Gowtham M 2025-12-18 10:35:20 +05:30
commit c90809b6ce

View File

@ -12,20 +12,6 @@ const Establishment = db.Establishment;
//Admin user and Establishment user login
exports.login = async (req, res) => {
try {
// Set security headers at the beginning
const isProd = process.env.NODE_ENV === "production";
// HSTS Header - Forces HTTPS for 1 year
if (isProd) {
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
}
// Additional security headers
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('Content-Security-Policy', "frame-ancestors 'none'");
const { email, password } = req.body;
let userRole = null;
@ -45,48 +31,18 @@ exports.login = async (req, res) => {
// No user found
if (!userData) {
// Set headers even for error responses
if (isProd) {
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
}
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-Content-Type-Options', 'nosniff');
return res.status(404).json({
status: "failed",
message: "Invalid user",
data: ""
});
return res.status(404).json({ status: "failed", message: "Invalid user", data: "" });
}
// Check ACTIVE status
if (!userData.is_active) {
if (isProd) {
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
}
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-Content-Type-Options', 'nosniff');
return res.status(403).json({
status: "failed",
message: "User account is inactive",
data: ""
});
return res.status(403).json({ status: "failed", message: "User account is inactive", data: "" });
}
// Check password
const validPass = await bcrypt.compare(password, userData.password);
if (!validPass) {
if (isProd) {
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
}
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-Content-Type-Options', 'nosniff');
return res.status(401).json({
status: "failed",
message: "Invalid password"
});
return res.status(401).json({ status: "failed", message: "Invalid password" });
}
// Prepare token data
@ -118,37 +74,27 @@ exports.login = async (req, res) => {
expiresIn: "6h",
});
// Set token in HTTP-only cookie with secure settings
// Set token in HTTP-only cookie (IMPORTANT PART)
const isProd = process.env.NODE_ENV === "production";
res.cookie("auth_token", token, {
httpOnly: true,
secure: isProd,
sameSite: isProd ? "none" : "lax",
maxAge: 6 * 60 * 60 * 1000,
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
});
// Set security headers for success response
if (isProd) {
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
}
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-Content-Type-Options', 'nosniff');
// Return minimal user info (WITHOUT password)
// Optionally return minimal user info (WITHOUT password)
return res.status(200).json({
status: "success",
message: "Login successful",
data: tokenData,
});
// return res.status(200).json({ status: "success", message: "Login successful", data: token });
} catch (err) {
// Set security headers for error response
const isProd = process.env.NODE_ENV === "production";
if (isProd) {
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
}
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-Content-Type-Options', 'nosniff');
return res.status(500).json({
status: "failed",
message: err.message,