webupdate

This commit is contained in:
Local Server
2026-01-19 01:17:43 -06:00
parent 5b86f796d6
commit f8068ba54c
65 changed files with 2165 additions and 520 deletions

View File

@@ -891,12 +891,22 @@ const settingsHandler = (key) => ({
sendSuccess(res, { settings });
}),
post: asyncHandler(async (req, res) => {
const settings = req.body;
const newSettings = req.body;
// Get existing settings first and merge
const existingResult = await query(
"SELECT settings FROM site_settings WHERE key = $1",
[key],
);
const existingSettings =
existingResult.rows.length > 0 ? existingResult.rows[0].settings : {};
// Merge new settings with existing (new settings overwrite existing for same keys)
const mergedSettings = { ...existingSettings, ...newSettings };
await query(
`INSERT INTO site_settings (key, settings, updatedat)
VALUES ($1, $2, NOW())
ON CONFLICT (key) DO UPDATE SET settings = $2, updatedat = NOW()`,
[key, JSON.stringify(settings)],
[key, JSON.stringify(mergedSettings)],
);
sendSuccess(res, { message: `${key} settings saved successfully` });
}),

View File

@@ -83,12 +83,15 @@ router.get(
}),
);
// Get site settings
// Get site settings (from site_settings table with key='general')
router.get(
"/settings",
asyncHandler(async (req, res) => {
const result = await query("SELECT * FROM sitesettings LIMIT 1");
sendSuccess(res, { settings: result.rows[0] || {} });
const result = await query(
"SELECT settings FROM site_settings WHERE key = 'general'",
);
const settings = result.rows.length > 0 ? result.rows[0].settings : {};
sendSuccess(res, settings);
}),
);

View File

@@ -64,6 +64,12 @@ app.use(
],
connectSrc: ["'self'", "https://cdn.jsdelivr.net"],
objectSrc: ["'none'"],
frameSrc: [
"'self'",
"https://www.google.com",
"https://maps.google.com",
"https://www.openstreetmap.org",
],
upgradeInsecureRequests: !isDevelopment() ? [] : null,
},
},
@@ -72,11 +78,11 @@ app.use(
includeSubDomains: true,
preload: true,
},
frameguard: { action: "deny" },
frameguard: { action: "sameorigin" },
xssFilter: true,
noSniff: true,
referrerPolicy: { policy: "strict-origin-when-cross-origin" },
})
}),
);
// CORS configuration
@@ -85,7 +91,7 @@ if (process.env.CORS_ORIGIN) {
cors({
origin: process.env.CORS_ORIGIN.split(","),
credentials: true,
})
}),
);
}
@@ -95,7 +101,7 @@ app.set("trust proxy", 1);
// Body parsers
app.use(express.json({ limit: BODY_PARSER_LIMITS.JSON }));
app.use(
express.urlencoded({ extended: true, limit: BODY_PARSER_LIMITS.URLENCODED })
express.urlencoded({ extended: true, limit: BODY_PARSER_LIMITS.URLENCODED }),
);
// Fallback middleware for missing product images
@@ -105,7 +111,7 @@ const productImageFallback = (req, res, next) => {
"assets",
"images",
"products",
req.path
req.path,
);
if (fs.existsSync(imagePath)) {
@@ -117,7 +123,7 @@ const productImageFallback = (req, res, next) => {
"assets",
"images",
"products",
"placeholder.jpg"
"placeholder.jpg",
);
logger.debug("Serving placeholder image", { requested: req.path });
res.sendFile(placeholderPath);
@@ -150,7 +156,7 @@ app.use(
res.setHeader("Cache-Control", "public, max-age=86400"); // 1 day default
}
},
})
}),
);
app.use(
"/assets",
@@ -172,7 +178,7 @@ app.use(
res.setHeader("Cache-Control", "public, max-age=86400"); // 1 day for images
}
},
})
}),
);
// Optimized image serving with aggressive caching
app.use("/uploads", imageOptimization(path.join(baseDir, "uploads")));
@@ -183,7 +189,7 @@ app.use(
etag: true,
lastModified: true,
immutable: true,
})
}),
);
// Session middleware
@@ -194,12 +200,12 @@ if (
) {
if (!isDevelopment()) {
logger.error(
"CRITICAL: SESSION_SECRET environment variable must be set in production!"
"CRITICAL: SESSION_SECRET environment variable must be set in production!",
);
process.exit(1);
}
logger.warn(
"WARNING: Using insecure session secret. Set SESSION_SECRET in production!"
"WARNING: Using insecure session secret. Set SESSION_SECRET in production!",
);
}
@@ -224,7 +230,7 @@ app.use(
proxy: !isDevelopment(),
name: SESSION_CONFIG.SESSION_NAME,
rolling: true, // Reset session expiration on each request
})
}),
);
// Request logging
@@ -333,7 +339,7 @@ app.use(
maxAge: "1d",
etag: true,
lastModified: true,
})
}),
);
// Favicon route
@@ -353,7 +359,7 @@ app.get("/health", async (req, res) => {
try {
const dbHealth = await healthCheck();
const missingImages = CRITICAL_IMAGES.filter(
(img) => !fs.existsSync(path.join(baseDir, img))
(img) => !fs.existsSync(path.join(baseDir, img)),
);
const assetsHealthy = missingImages.length === 0;