GWM : cookies
This commit is contained in:
parent
4a99233ea1
commit
510fc030ec
@ -1637,8 +1637,18 @@ exports.establishmentBulkUpload = async (req, res) => {
|
|||||||
|
|
||||||
exports.downloadCompanyProfileSample = async (req, res) => {
|
exports.downloadCompanyProfileSample = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const filePath = path.join(__dirname, "../uploads/company_profile_upload_sample.csv");
|
const safeBasePath = path.resolve(__dirname, "../uploads");
|
||||||
return res.download(filePath, "company_profile_upload_sample.csv");
|
const safeFilePath = path.join(safeBasePath, "company_profile_upload_sample.csv");
|
||||||
|
|
||||||
|
// Verify file exists BEFORE sending
|
||||||
|
if (!fs.existsSync(safeFilePath)) {
|
||||||
|
return res.status(404).send({
|
||||||
|
status: "failed",
|
||||||
|
message: "File not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.download(safeFilePath, "unit_master_sample.csv");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return res.status(500).send({ status: "failed", message: error.message });
|
return res.status(500).send({ status: "failed", message: error.message });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -179,7 +179,7 @@ exports.uploadUnitMasterFromCSV = async (req, res) => {
|
|||||||
if (!req.file)
|
if (!req.file)
|
||||||
return res.status(400).send({ status: "failed", message: "No file uploaded." });
|
return res.status(400).send({ status: "failed", message: "No file uploaded." });
|
||||||
|
|
||||||
const filePath = req.file.path;
|
const filePath = path.resolve(req.file.path);
|
||||||
|
|
||||||
// Validate file type
|
// Validate file type
|
||||||
if (!req.file.originalname.endsWith(".csv")) {
|
if (!req.file.originalname.endsWith(".csv")) {
|
||||||
@ -431,7 +431,7 @@ exports.uploadUnitMasterFromCSV = async (req, res) => {
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error uploading Unit Master CSV:", error);
|
console.error("Error uploading Unit Master CSV:", error);
|
||||||
if (req.file && fs.existsSync(req.file.path)) fs.unlinkSync(req.file.path);
|
if (req.file && fs.existsSync(path.resolve(req.file.path))) fs.unlinkSync(path.resolve(req.file.path));
|
||||||
return res.status(500).send({
|
return res.status(500).send({
|
||||||
status: "failed",
|
status: "failed",
|
||||||
message: "Error processing CSV file.",
|
message: "Error processing CSV file.",
|
||||||
@ -440,11 +440,33 @@ exports.uploadUnitMasterFromCSV = async (req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// exports.downloadUnitMasterFile = async (req, res) => {
|
||||||
|
// try {
|
||||||
|
// const filePath = path.join(__dirname, "../uploads/unit_master_sample.csv");
|
||||||
|
// return res.download(filePath, "unit_master_sample.csv");
|
||||||
|
// } catch (error) {
|
||||||
|
// return res.status(500).send({ status: "failed", message: error.message });
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
exports.downloadUnitMasterFile = async (req, res) => {
|
exports.downloadUnitMasterFile = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const filePath = path.join(__dirname, "../uploads/unit_master_sample.csv");
|
const safeBasePath = path.resolve(__dirname, "../uploads");
|
||||||
return res.download(filePath, "unit_master_sample.csv");
|
const safeFilePath = path.join(safeBasePath, "unit_master_sample.csv");
|
||||||
|
|
||||||
|
// Verify file exists BEFORE sending
|
||||||
|
if (!fs.existsSync(safeFilePath)) {
|
||||||
|
return res.status(404).send({
|
||||||
|
status: "failed",
|
||||||
|
message: "File not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.download(safeFilePath, "unit_master_sample.csv");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return res.status(500).send({ status: "failed", message: error.message });
|
return res.status(500).send({
|
||||||
|
status: "failed",
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -17,7 +17,7 @@ exports.createUser = async (req, res) => {
|
|||||||
|
|
||||||
logger.info(`User created: ${email}`);
|
logger.info(`User created: ${email}`);
|
||||||
|
|
||||||
res.status(201).send({'status':"success",'message':"created successfully",'data': user });
|
res.status(201).send({'status':"success",'message':"created successfully" });
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err.message);
|
logger.error(err.message);
|
||||||
|
|||||||
@ -64,6 +64,30 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
{
|
{
|
||||||
timestamps: false,
|
timestamps: false,
|
||||||
tableName: "establishment_users",
|
tableName: "establishment_users",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 1. EXCLUDE sensitive fields from all queries
|
||||||
|
defaultScope: {
|
||||||
|
attributes: { exclude: ["password", "reset_otp", "reset_otp_expires_at"] },
|
||||||
|
},
|
||||||
|
|
||||||
|
// 2. Ensure manual selections still hide sensitive fields
|
||||||
|
scopes: {
|
||||||
|
withSensitive: {
|
||||||
|
attributes: { include: ["password", "reset_otp", "reset_otp_expires_at"] },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// 3. Remove sensitive fields when converting to JSON
|
||||||
|
instanceMethods: {
|
||||||
|
toJSON() {
|
||||||
|
const values = { ...this.get() };
|
||||||
|
delete values.password;
|
||||||
|
delete values.reset_otp;
|
||||||
|
delete values.reset_otp_expires_at;
|
||||||
|
return values;
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,32 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
type: DataTypes.BOOLEAN,
|
type: DataTypes.BOOLEAN,
|
||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
{
|
||||||
|
// 1. EXCLUDE sensitive fields from all queries
|
||||||
|
defaultScope: {
|
||||||
|
attributes: { exclude: ["password", "reset_otp", "reset_otp_expires_at"] },
|
||||||
|
},
|
||||||
|
|
||||||
|
// 2. Ensure manual selections still hide sensitive fields
|
||||||
|
scopes: {
|
||||||
|
withSensitive: {
|
||||||
|
attributes: { include: ["password", "reset_otp", "reset_otp_expires_at"] },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// 3. Remove sensitive fields when converting to JSON
|
||||||
|
instanceMethods: {
|
||||||
|
toJSON() {
|
||||||
|
const values = { ...this.get() };
|
||||||
|
delete values.password;
|
||||||
|
delete values.reset_otp;
|
||||||
|
delete values.reset_otp_expires_at;
|
||||||
|
return values;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return User;
|
return User;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -23,9 +23,12 @@ function sanitizeValue(value) {
|
|||||||
return value; // numbers, booleans, null
|
return value; // numbers, booleans, null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = function sanitizeInput(req, res, next) {
|
module.exports = function sanitizeInput(req, res, next) {
|
||||||
if (req.body) {
|
if (req.body) req.body = sanitizeValue(req.body);
|
||||||
req.body = sanitizeValue(req.body);
|
if (req.query) req.query = sanitizeValue(req.query);
|
||||||
}
|
if (req.params) req.params = sanitizeValue(req.params);
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
17
server.js
17
server.js
@ -21,6 +21,23 @@ app.use(
|
|||||||
contentSecurityPolicy: false,
|
contentSecurityPolicy: false,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
// prevent framing (clickjacking protection)
|
||||||
|
app.use(
|
||||||
|
helmet.frameguard({
|
||||||
|
action: "deny",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add HSTS explicitly (fixes scanner warning)
|
||||||
|
if (process.env.NODE_ENV === "production") {
|
||||||
|
app.use(
|
||||||
|
helmet.hsts({
|
||||||
|
maxAge: 31536000, // 1 year
|
||||||
|
includeSubDomains: true,
|
||||||
|
preload: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
app.use(morgan("dev"));
|
app.use(morgan("dev"));
|
||||||
app.use(sanitizeInput);
|
app.use(sanitizeInput);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user