修复安全与备份问题

This commit is contained in:
lizhilun
2026-07-12 17:50:04 +08:00
parent 77cd66a854
commit b728ae08e4
7 changed files with 65 additions and 30 deletions
+18 -9
View File
@@ -21,6 +21,23 @@ function nullableDbValue(value) {
return value === undefined || value === null || value === '' ? null : value;
}
const csvTextFields = new Set(['type', 'category', 'boss', 'partner', 'source', 'destination', 'note', 'created_at']);
function escapeCsvFormula(value) {
return /^[\t\r=+\-@]/.test(value) || /^[ \t]+[=+\-@]/.test(value)
? `'${value}`
: value;
}
function encodeCsvCell(value, col) {
if (value === null || value === undefined) return '';
const str = csvTextFields.has(col) ? escapeCsvFormula(String(value)) : String(value);
if (str.includes(',') || str.includes('"') || str.includes('\n') || str.includes('\r')) {
return '"' + str.replace(/"/g, '""') + '"';
}
return str;
}
// 导出数据
router.get('/export', (req, res, next) => {
try {
@@ -54,15 +71,7 @@ router.get('/export', (req, res, next) => {
const BOM = '\uFEFF';
const cols = ['type', 'category', 'amount', 'quantity', 'unit_price', 'rebate', 'boss', 'partner', 'source', 'destination', 'note', 'created_at'];
const csvRows = records.map(r => {
return cols.map(col => {
const val = r[col];
if (val === null || val === undefined) return '';
const str = String(val);
if (str.includes(',') || str.includes('"') || str.includes('\n')) {
return '"' + str.replace(/"/g, '""') + '"';
}
return str;
}).join(',');
return cols.map(col => encodeCsvCell(r[col], col)).join(',');
});
logger.info(`用户 ${req.user.username} 导出 CSV 数据: ${records.length}`);
res.setHeader('Content-Type', 'text/csv; charset=utf-8');