165 lines
4.0 KiB
TypeScript
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',
|
|
});
|
|
});
|