security: fix all Medium findings from FLAWS_REPORT audit
- Auth: TOTP replay protection with counter tracking, constant-time backup code comparison, atomic lockout increment, per-token logout - Invoices/PDFs: net-based VAT calculation, dangerous URL scheme stripping in cleanQuillHtml, orders-pdf error handling - Orders: reject item changes on status transition, cascading delete cleanup, take:1 with orderBy - Projects: atomic rename collision handling, MIME/extension validation, empty customer name rejection - Attendance: Czech public holiday awareness in frontend fund calculation, leave_hours 0 handling, invalid date NaN guard, bounded per-month queries in workfund - Users/Admin: profile audit logging + password validation, session revocation guard, session ID validation, dashboard DB aggregation, soft-deleted record protection in scope templates - Frontend: FormField label linkage, Pagination ARIA, error handling in OrderConfirmationModal, 401 propagation, GPS emoji hidden from screen readers, table sort state fix, geolocation race/abort cleanup, Leaflet popup DOM safety, Vehicles toggleActive minimal body, CompanySettings ref mutation fix, OfferDetail unlock abort, AttendanceBalances combined fetches - Utils: env validation, Puppeteer concurrency mutex, invoice alert cron cleanup on shutdown, body limit alignment, TOTP error logging, trustProxy from env, symlink rejection, rate cache Map usage Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -36,13 +36,14 @@ const app = Fastify({
|
||||
logger: {
|
||||
level: config.isProduction ? "warn" : "info",
|
||||
},
|
||||
trustProxy: config.isProduction
|
||||
? ["127.0.0.1", "192.168.50.100"]
|
||||
: ["127.0.0.1", "::1"],
|
||||
bodyLimit: 1048576,
|
||||
trustProxy:
|
||||
config.trustProxy.length > 0 ? config.trustProxy : ["127.0.0.1", "::1"],
|
||||
bodyLimit: config.nas.maxUploadSize,
|
||||
});
|
||||
|
||||
async function start() {
|
||||
let invoiceAlertCron: any = null;
|
||||
|
||||
// --- Plugins ---
|
||||
await app.register(cors, {
|
||||
origin:
|
||||
@@ -184,7 +185,7 @@ async function start() {
|
||||
// --- Invoice alert cron (daily at 8:00 AM) ---
|
||||
if (config.email.invoiceAlert) {
|
||||
const cron = await import("node-cron");
|
||||
cron.default.schedule("0 8 * * *", async () => {
|
||||
invoiceAlertCron = cron.default.schedule("0 8 * * *", async () => {
|
||||
try {
|
||||
const { checkInvoiceAlerts } =
|
||||
await import("./services/invoice-alerts");
|
||||
@@ -209,6 +210,9 @@ async function start() {
|
||||
const shutdown = async (signal: string) => {
|
||||
app.log.info(`${signal} received, shutting down gracefully...`);
|
||||
try {
|
||||
if (invoiceAlertCron) {
|
||||
invoiceAlertCron.stop();
|
||||
}
|
||||
await app.close();
|
||||
const { default: prisma } = await import("./config/database");
|
||||
await prisma.$disconnect();
|
||||
|
||||
Reference in New Issue
Block a user