← back to Credentials Agentabrams

server.js

58 lines

// credentials.agentabrams.com — pending credential-actions dashboard
// Basic-auth (admin/DW2024!), zero-dependency Node http. Serves public/ + /api/credentials.
const http = require('http');
const fs = require('fs');
const path = require('path');

const PORT = process.env.PORT || 9769;
const USER = process.env.BASIC_USER || 'admin';
const PASS = process.env.BASIC_PASS || 'DW2024!';
const ROOT = __dirname;

const MIME = { '.html': 'text/html; charset=utf-8', '.css': 'text/css', '.js': 'application/javascript', '.json': 'application/json' };

function unauthorized(res) {
  res.writeHead(401, { 'WWW-Authenticate': 'Basic realm="credentials", charset="UTF-8"' });
  res.end('Auth required');
}

function checkAuth(req) {
  const h = req.headers.authorization || '';
  if (!h.startsWith('Basic ')) return false;
  const [u, p] = Buffer.from(h.slice(6), 'base64').toString().split(':');
  return u === USER && p === PASS;
}

const server = http.createServer((req, res) => {
  if (!checkAuth(req)) return unauthorized(res);

  if (req.url === '/api/credentials') {
    try {
      const data = fs.readFileSync(path.join(ROOT, 'data', 'credentials.json'), 'utf8');
      res.writeHead(200, { 'Content-Type': 'application/json' });
      return res.end(data);
    } catch (e) {
      res.writeHead(500, { 'Content-Type': 'application/json' });
      return res.end(JSON.stringify({ error: String(e) }));
    }
  }

  if (req.url === '/health') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    return res.end(JSON.stringify({ ok: true, port: PORT }));
  }

  // static
  let rel = req.url.split('?')[0];
  if (rel === '/' || rel === '') rel = '/index.html';
  const filePath = path.join(ROOT, 'public', path.normalize(rel));
  if (!filePath.startsWith(path.join(ROOT, 'public'))) { res.writeHead(403); return res.end('forbidden'); }
  fs.readFile(filePath, (err, buf) => {
    if (err) { res.writeHead(404); return res.end('not found'); }
    res.writeHead(200, { 'Content-Type': MIME[path.extname(filePath)] || 'application/octet-stream' });
    res.end(buf);
  });
});

server.listen(PORT, () => console.log(`credentials dashboard on http://127.0.0.1:${PORT} (admin/DW2024!)`));