[object Object]

← back to Hospitalitydesignreps

Gate site behind HTTP Basic Auth (admin/DW2024!, env-overridable); /healthz stays open

be7cb6128e1abd0953438656b25d34a1d151c3da · 2026-06-30 04:24:35 -0700 · Steve

Files touched

Diff

commit be7cb6128e1abd0953438656b25d34a1d151c3da
Author: Steve <steve@designerwallcoverings.com>
Date:   Tue Jun 30 04:24:35 2026 -0700

    Gate site behind HTTP Basic Auth (admin/DW2024!, env-overridable); /healthz stays open
---
 server.js | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/server.js b/server.js
index ebc2a45..2c6c0d4 100644
--- a/server.js
+++ b/server.js
@@ -21,6 +21,25 @@ app.use(helmet({
 app.use(compression());
 app.use(morgan('tiny'));
 
+// HTTP Basic Auth gate (Steve: admin / DW2024!). Env-overridable. /healthz stays open so the
+// fleet uptime/canary probes still work without credentials.
+const BASIC_USER = process.env.BASIC_AUTH_USER || 'admin';
+const BASIC_PASS = process.env.BASIC_AUTH_PASS || 'DW2024!';
+app.use((req, res, next) => {
+  if (req.path === '/healthz') return next();
+  const hdr = req.headers.authorization || '';
+  const [scheme, b64] = hdr.split(' ');
+  if (scheme === 'Basic' && b64) {
+    const decoded = Buffer.from(b64, 'base64').toString();
+    const idx = decoded.indexOf(':');
+    const u = decoded.slice(0, idx);
+    const p = decoded.slice(idx + 1);   // rejoin rest so a ':' in the password is preserved
+    if (u === BASIC_USER && p === BASIC_PASS) return next();
+  }
+  res.set('WWW-Authenticate', 'Basic realm="Hospitality Design Reps"');
+  return res.status(401).send('Authentication required.');
+});
+
 app.use((req, res, next) => {
   res.set('Cache-Control', 'no-store, must-revalidate');
   next();

← 6245258 auto-save: 2026-06-30T03:57:50 (1 files) — data/reps.json  ·  back to Hospitalitydesignreps  ·  Add scraped phone/email/LinkedIn to 24 real reps + Direct-co 98b6aa3 →