39948-vm/backend/tests/runtime-public.test.ts
2026-07-02 14:22:33 +02:00

165 lines
4.0 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import type { NextFunction, Request, RequestHandler } from 'express';
import { createRequest, createResponse } from 'node-mocks-http';
import {
blockNonPublicRuntimeListEndpoints,
sanitizePublicRuntimeListResponse,
} from '../src/middlewares/runtime-public.ts';
import { setRuntimePublicRequest } from '../src/utils/request-context.ts';
function runMiddleware(
middleware: RequestHandler,
req: Request,
): Promise<boolean> {
const res = createResponse();
return new Promise((resolve, reject) => {
const next: NextFunction = (error?: unknown) => {
if (error) {
reject(
error instanceof Error
? error
: new Error('Middleware returned a non-Error callback value.'),
);
return;
}
resolve(true);
};
middleware(req, res, next);
if (res._isEndCalled()) {
resolve(false);
}
});
}
void test('blockNonPublicRuntimeListEndpoints blocks public runtime CSV exports', () => {
const req = createRequest({
method: 'GET',
url: '/?filetype=csv',
query: { filetype: 'csv' },
});
setRuntimePublicRequest(req, true);
const res = createResponse();
let nextCalled = false;
blockNonPublicRuntimeListEndpoints('projects')(req, res, () => {
nextCalled = true;
});
assert.equal(nextCalled, false);
assert.equal(res.statusCode, 404);
assert.deepEqual(res._getData(), { message: 'Not found' });
});
void test('blockNonPublicRuntimeListEndpoints blocks non-allowed public runtime paths', () => {
const req = createRequest({
method: 'GET',
url: '/autocomplete',
});
setRuntimePublicRequest(req, true);
const res = createResponse();
let nextCalled = false;
blockNonPublicRuntimeListEndpoints('projects')(req, res, () => {
nextCalled = true;
});
assert.equal(nextCalled, false);
assert.equal(res.statusCode, 404);
});
void test('blockNonPublicRuntimeListEndpoints allows configured runtime project settings path', async () => {
const req = createRequest({
method: 'GET',
url: '/project/094121b9-c567-469a-b256-ba221b7fd5d6/env/production',
});
setRuntimePublicRequest(req, true);
assert.equal(
await runMiddleware(
blockNonPublicRuntimeListEndpoints('project_transition_settings'),
req,
),
true,
);
});
void test('sanitizePublicRuntimeListResponse strips non-public fields from rows and records', () => {
const listReq = createRequest({
method: 'GET',
url: '/',
});
setRuntimePublicRequest(listReq, true);
const listRes = createResponse();
sanitizePublicRuntimeListResponse('projects')(listReq, listRes, () => {});
listRes.send({
rows: [
{
id: 'project-1',
name: 'Lobby',
slug: 'lobby',
secret: 'do-not-leak',
},
],
count: 1,
});
assert.deepEqual(listRes._getData(), {
rows: [
{
id: 'project-1',
name: 'Lobby',
slug: 'lobby',
},
],
count: 1,
});
const recordReq = createRequest({
method: 'GET',
url: '/',
});
setRuntimePublicRequest(recordReq, true);
const recordRes = createResponse();
sanitizePublicRuntimeListResponse('tour_pages')(recordReq, recordRes, () => {});
recordRes.send({
id: 'page-1',
slug: 'intro',
ui_schema_json: { elements: [] },
internal_note: 'do-not-leak',
});
assert.deepEqual(recordRes._getData(), {
id: 'page-1',
slug: 'intro',
ui_schema_json: { elements: [] },
});
});
void test('sanitizePublicRuntimeListResponse does not affect authenticated admin requests', () => {
const req = createRequest({
method: 'GET',
url: '/',
});
const res = createResponse();
sanitizePublicRuntimeListResponse('projects')(req, res, () => {});
res.send({
id: 'project-1',
slug: 'lobby',
secret: 'visible-to-admin-path',
});
assert.deepEqual(res._getData(), {
id: 'project-1',
slug: 'lobby',
secret: 'visible-to-admin-path',
});
});