Refactor: Harden for Production

This commit refactors the Node.js server to be production-ready.

- **Strict Production Environment:** The server now checks for . If it is set, the server will refuse to start unless a secure  is provided as an environment variable. This prevents running with the insecure default password in production.
- **Logging:** Added basic logging for successful status updates and failed login attempts.
- **NPM Scripts:** Added a  script to  for starting the server in production mode ().
This commit is contained in:
chris 2025-11-12 14:26:11 -05:00
parent 07b83c7ae8
commit 74aa30636c
2 changed files with 27 additions and 10 deletions

View File

@ -5,6 +5,7 @@
"main": "admin.js", "main": "admin.js",
"scripts": { "scripts": {
"start": "node server.js", "start": "node server.js",
"start:prod": "NODE_ENV=production node server.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"keywords": [], "keywords": [],

View File

@ -1,22 +1,34 @@
require('dotenv').config(); // Load environment variables from .env file for development
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config();
}
const express = require('express'); const express = require('express');
const bodyParser = require('body-parser'); const bodyParser = require('body-parser');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const app = express(); const app = express();
const port = 3050; const port = 3000;
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD;
// IMPORTANT: In a production environment, set the ADMIN_PASSWORD as an environment variable. // --- Production Security Check ---
// For example: export ADMIN_PASSWORD="your_super_secret_password" if (process.env.NODE_ENV === 'production' && (!ADMIN_PASSWORD || ADMIN_PASSWORD === "balloons")) {
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || "balloons"; console.error(`
****************************************************************
** FATAL ERROR: Insecure password configuration for production! **
** Please set a secure ADMIN_PASSWORD environment variable. **
****************************************************************
`);
process.exit(1); // Exit the process with an error code
}
if (ADMIN_PASSWORD === "balloons") { // --- Development Warning ---
if (process.env.NODE_ENV !== 'production' && ADMIN_PASSWORD === "balloons") {
console.warn(` console.warn(`
**************************************************************** ****************************************************************
** WARNING: Using default, insecure password. ** ** WARNING: Using default, insecure password. **
** Please set a secure ADMIN_PASSWORD environment variable ** ** This is for development only. **
** in your production environment. **
**************************************************************** ****************************************************************
`); `);
} }
@ -32,6 +44,7 @@ app.post('/api/update-status', (req, res) => {
const { password, data } = req.body; const { password, data } = req.body;
if (password !== ADMIN_PASSWORD) { if (password !== ADMIN_PASSWORD) {
console.log(`[${new Date().toISOString()}] Failed login attempt.`);
return res.status(401).json({ success: false, message: 'Unauthorized: Incorrect password.' }); return res.status(401).json({ success: false, message: 'Unauthorized: Incorrect password.' });
} }
@ -44,14 +57,17 @@ app.post('/api/update-status', (req, res) => {
fs.writeFile(filePath, jsonString, (err) => { fs.writeFile(filePath, jsonString, (err) => {
if (err) { if (err) {
console.error('Error writing to update.json:', err); console.error(`[${new Date().toISOString()}] Error writing to update.json:`, err);
return res.status(500).json({ success: false, message: 'Internal Server Error: Could not write to file.' }); return res.status(500).json({ success: false, message: 'Internal Server Error: Could not write to file.' });
} }
console.log(`[${new Date().toISOString()}] update.json was successfully updated.`);
res.json({ success: true, message: 'Status updated successfully.' }); res.json({ success: true, message: 'Status updated successfully.' });
}); });
}); });
app.listen(port, () => { app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`); console.log(`Server listening at http://localhost:${port}`);
console.log(`Admin panel available at http://localhost:${port}/admin.html`); if (process.env.NODE_ENV !== 'production') {
console.log(`Admin panel available at http://localhost:${port}/admin.html`);
}
}); });