← back to Costa Rica

test/admin-gate-configured.test.js

58 lines

'use strict';
// Companion to admin-gate-fail-closed.test.js (TK-10346, Steve-approved option B):
// this is the GREEN/unchanged case. When BASIC_AUTH_USER/PASS ARE set (today's real
// config), the new fail-closed guard must be a total no-op — an unauthenticated
// admin request is rejected 401 by the pre-existing site-wide basic-auth gate
// exactly as before, and never even reaches the new middleware's 503 branch.
//
// Pin BASIC_AUTH_USER/PASS BEFORE requiring server.js (same pattern as
// test/server-routes.test.js) so this wins over whatever the real .env has.
process.env.BASIC_AUTH_USER = 'testuser';
process.env.BASIC_AUTH_PASS = 'testpass';

const { test, before, after } = require('node:test');
const assert = require('node:assert');
const http = require('node:http');

const app = require('../server'); // exported app, does NOT listen on import

const AUTH = 'Basic ' + Buffer.from('testuser:testpass').toString('base64');

let server, base;
before(async () => {
  await new Promise(r => { server = app.listen(0, r); });
  base = `http://127.0.0.1:${server.address().port}`;
});
after(async () => {
  server && server.close();
  try { await app.locals.pool.end(); } catch { /* already closed */ }
});

function get(path, headers) {
  return new Promise((resolve, reject) => {
    http.get(base + path, { headers: headers || {} }, res => {
      let b = ''; res.on('data', c => b += c);
      res.on('end', () => resolve({ status: res.statusCode, body: b }));
    }).on('error', reject);
  });
}

test('GET /api/admin/stats WITHOUT credentials -> 401 as before (gate configured, unchanged)', async () => {
  const r = await get('/api/admin/stats');
  assert.equal(r.status, 401);
});

test('GET /admin WITHOUT credentials -> 401 as before (gate configured, unchanged)', async () => {
  const r = await get('/admin');
  assert.equal(r.status, 401);
});

test('GET /api/admin/stats WITH valid credentials reaches the router (not blocked by the new guard)', async () => {
  const r = await get('/api/admin/stats', { authorization: AUTH });
  // Real dev DB: either the query succeeds (200) or the app's generic 500 handler
  // fires — either way it must NOT be 401 (creds accepted) or 503 (guard is a no-op
  // once the gate is configured); 503 is reserved for the unconfigured case only.
  assert.notEqual(r.status, 401, 'valid credentials must pass the basic-auth gate');
  assert.notEqual(r.status, 503, 'the fail-closed guard must be a no-op when BASIC_AUTH_* is set');
});