import request from 'supertest'; import app from '../../src/app'; import { pool } from '../../src/db'; import { resetDb, closeDb } from './setup/testDb'; // The unit tests prove the middleware decides correctly. This proves it is // actually attached to the admin routers — a correct function nobody mounted // would pass every unit test and protect nothing. // // ADMIN_GATE_SECRET is read per request rather than at import, so it can be set // here without reloading the app. It is restored after each test so this file // cannot change how anything running later in the same process behaves. const SECRET = 'integration-gate-secret'; const original = process.env.ADMIN_GATE_SECRET; let warn: jest.SpyInstance; beforeEach(async () => { await resetDb(); warn = jest.spyOn(console, 'warn').mockImplementation(() => undefined); }); afterEach(() => { warn.mockRestore(); if (original === undefined) { delete process.env.ADMIN_GATE_SECRET; } else { process.env.ADMIN_GATE_SECRET = original; } }); afterAll(async () => { await pool.end(); await closeDb(); }); describe('the admin gate, mounted on the real routers', () => { it('refuses an admin request with no gate header once a secret is configured', async () => { process.env.ADMIN_GATE_SECRET = SECRET; const res = await request(app).get('/api/admin/items'); expect(res.status).toBe(403); expect(res.body.error).toBe('forbidden'); }); it('serves the same request when it carries the gate header', async () => { process.env.ADMIN_GATE_SECRET = SECRET; const res = await request(app).get('/api/admin/items').set('X-Admin-Gate', SECRET); expect(res.status).toBe(200); expect(Array.isArray(res.body)).toBe(true); }); // Every admin router has to be covered, not just the one mounted last. These // are separate app.use calls, so one of them missing the middleware is an // easy and completely silent mistake. it.each([ ['/api/admin/customers', 'customers'], ['/api/admin/categories', 'categories'], ['/api/admin/tags', 'tags'], ['/api/admin/settings', 'settings'], ['/api/admin/items', 'inventory'] ])('gates %s', async (path) => { process.env.ADMIN_GATE_SECRET = SECRET; const refused = await request(app).get(path); expect(refused.status).toBe(403); const allowed = await request(app).get(path).set('X-Admin-Gate', SECRET); expect(allowed.status).not.toBe(403); }); // The state every existing admin test relies on, and the state production // runs in until the proxy is configured. it('leaves admin reachable when no secret is configured', async () => { delete process.env.ADMIN_GATE_SECRET; const res = await request(app).get('/api/admin/items'); expect(res.status).toBe(200); }); // The storefront must not be caught by the gate — it is public by design and // the proxy does not add the header to it in production. it('does not gate the public storefront', async () => { process.env.ADMIN_GATE_SECRET = SECRET; const res = await request(app).get('/api/items'); expect(res.status).toBe(200); }); });