Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4264026bbe | |||
| 24b4a314a9 | |||
| ba825823a0 | |||
| fb16b7bbb8 |
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "picpeak-backend",
|
||||
"version": "1.0.117",
|
||||
"version": "1.0.119",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "picpeak-backend",
|
||||
"version": "1.0.117",
|
||||
"version": "1.0.119",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.850.0",
|
||||
"@aws-sdk/lib-storage": "^3.850.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "picpeak-backend",
|
||||
"version": "1.0.117",
|
||||
"version": "1.0.119",
|
||||
"description": "Backend for PicPeak event photo sharing platform",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
||||
+32
-16
@@ -43,25 +43,36 @@ const PORT = process.env.PORT || 3000;
|
||||
app.set('trust proxy', 'loopback, linklocal, uniquelocal');
|
||||
|
||||
// Security middleware with custom CSP
|
||||
// In native HTTP installs, do NOT force HTTPS for subresources.
|
||||
const enableHsts = process.env.ENABLE_HSTS === 'true';
|
||||
const cspDirectives = {
|
||||
defaultSrc: ["'self'"],
|
||||
scriptSrc: ["'self'", "'unsafe-inline'"], // Required for React
|
||||
styleSrc: ["'self'", "'unsafe-inline'", "https:"], // Required for styled components
|
||||
imgSrc: ["'self'", "data:", "https:", "blob:"], // Allow data URLs and external images
|
||||
connectSrc: ["'self'"], // API connections
|
||||
fontSrc: ["'self'", "https:", "data:"], // Web fonts
|
||||
objectSrc: ["'none'"], // Disable plugins
|
||||
mediaSrc: ["'self'"], // Audio/video
|
||||
frameSrc: ["'none'"], // Disable iframes
|
||||
};
|
||||
// Only upgrade insecure requests when HSTS explicitly enabled (HTTPS deployment)
|
||||
if (enableHsts) {
|
||||
// In helmet, an empty array enables the directive
|
||||
cspDirectives.upgradeInsecureRequests = [];
|
||||
}
|
||||
|
||||
app.use(helmet({
|
||||
contentSecurityPolicy: {
|
||||
directives: {
|
||||
defaultSrc: ["'self'"],
|
||||
scriptSrc: ["'self'", "'unsafe-inline'"], // Required for React
|
||||
styleSrc: ["'self'", "'unsafe-inline'", "https:"], // Required for styled components
|
||||
imgSrc: ["'self'", "data:", "https:", "blob:"], // Allow data URLs and external images
|
||||
connectSrc: ["'self'"], // API connections
|
||||
fontSrc: ["'self'", "https:", "data:"], // Web fonts
|
||||
objectSrc: ["'none'"], // Disable plugins
|
||||
mediaSrc: ["'self'"], // Audio/video
|
||||
frameSrc: ["'none'"], // Disable iframes
|
||||
},
|
||||
// Avoid helmet adding defaults like upgrade-insecure-requests when not desired
|
||||
useDefaults: false,
|
||||
directives: cspDirectives,
|
||||
},
|
||||
hsts: {
|
||||
hsts: enableHsts ? {
|
||||
maxAge: 31536000, // 1 year
|
||||
includeSubDomains: true,
|
||||
preload: true
|
||||
},
|
||||
} : false,
|
||||
permittedCrossDomainPolicies: false,
|
||||
referrerPolicy: { policy: "strict-origin-when-cross-origin" }
|
||||
}));
|
||||
@@ -222,15 +233,20 @@ app.use('/api/secure-images', secureImagesRoutes);
|
||||
|
||||
// Optional: Serve built frontend (native installs)
|
||||
try {
|
||||
const serveFrontend = process.env.SERVE_FRONTEND === 'true';
|
||||
const serveFrontendEnv = process.env.SERVE_FRONTEND; // 'true' | 'false' | undefined
|
||||
const frontendDir = process.env.FRONTEND_DIR || path.join(__dirname, '../frontend/dist');
|
||||
if (serveFrontend && fs.existsSync(frontendDir)) {
|
||||
const indexPath = path.join(frontendDir, 'index.html');
|
||||
// Auto-serve when dist exists unless explicitly disabled
|
||||
const shouldServe = (serveFrontendEnv === 'true') || ((serveFrontendEnv === undefined || serveFrontendEnv === 'auto') && fs.existsSync(indexPath));
|
||||
if (shouldServe) {
|
||||
logger.info(`Serving frontend from ${frontendDir}`);
|
||||
app.use(express.static(frontendDir));
|
||||
// SPA fallback for non-API routes
|
||||
app.get([ '/', '/admin', '/admin/*', '/gallery/*' ], (req, res) => {
|
||||
res.sendFile(path.join(frontendDir, 'index.html'));
|
||||
res.sendFile(indexPath);
|
||||
});
|
||||
} else {
|
||||
logger.info('Frontend static serving disabled or dist not found', { serveFrontendEnv, frontendDir });
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn('Failed to enable frontend static serving', { error: e.message });
|
||||
|
||||
Reference in New Issue
Block a user