chore: import DH V2 D5.6.4 production baseline
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import type { DataSource, EntityManager } from 'typeorm';
|
||||
import { AuditQueryService } from '../../src/audit/audit-query.service';
|
||||
import { buildAuditFilters } from '../../src/audit/audit-query';
|
||||
import { ListAuditQueryDto } from '../../src/audit/dto/list-audit-query.dto';
|
||||
import { AuditSource } from '../../src/database/entities';
|
||||
|
||||
test('buildAuditFilters parameterizes every audit filter', () => {
|
||||
const query = Object.assign(new ListAuditQueryDto(), {
|
||||
actorUsername: 'admin',
|
||||
action: 'USER_CREATED',
|
||||
source: AuditSource.WEB,
|
||||
entityType: 'user',
|
||||
requestId: 'request-12345678',
|
||||
from: '2026-08-01T00:00:00.000Z',
|
||||
to: '2026-08-31T23:59:59.999Z',
|
||||
search: "anything' OR 1=1 --",
|
||||
});
|
||||
|
||||
const filters = buildAuditFilters(query);
|
||||
assert.match(filters.clause, /event\.actor_username ILIKE \$1/);
|
||||
assert.match(filters.clause, /event\.action = \$2/);
|
||||
assert.match(filters.clause, /event\.source = \$3/);
|
||||
assert.match(filters.clause, /event\.occurred_at >= \$6/);
|
||||
assert.match(filters.clause, /event\.occurred_at <= \$7/);
|
||||
assert.match(filters.clause, /event\.request_id ILIKE \$8/);
|
||||
assert.equal(filters.clause.includes("anything' OR 1=1"), false);
|
||||
assert.equal(filters.parameters[7], "%anything' OR 1=1 --%");
|
||||
});
|
||||
|
||||
test('AuditQueryService rejects an inverted date range before querying', async () => {
|
||||
const dataSource = {
|
||||
transaction: () => {
|
||||
throw new Error('transaction should not run');
|
||||
},
|
||||
} as unknown as DataSource;
|
||||
const service = new AuditQueryService(dataSource);
|
||||
const query = Object.assign(new ListAuditQueryDto(), {
|
||||
from: '2026-08-31T00:00:00.000Z',
|
||||
to: '2026-08-01T00:00:00.000Z',
|
||||
});
|
||||
|
||||
await assert.rejects(
|
||||
service.list(query),
|
||||
(error: unknown) =>
|
||||
error instanceof BadRequestException && error.getStatus() === 400,
|
||||
);
|
||||
});
|
||||
|
||||
test('AuditQueryService returns stable pagination metadata', async () => {
|
||||
let calls = 0;
|
||||
const manager = {
|
||||
query: async () => {
|
||||
calls += 1;
|
||||
return calls === 1
|
||||
? [{ total: 26 }]
|
||||
: [
|
||||
{
|
||||
id: '0f45472b-541b-4d6c-969f-0821463d0ea7',
|
||||
action: 'USER_CREATED',
|
||||
},
|
||||
];
|
||||
},
|
||||
} as unknown as EntityManager;
|
||||
const dataSource = {
|
||||
transaction: async (
|
||||
_isolation: string,
|
||||
operation: (entityManager: EntityManager) => Promise<unknown>,
|
||||
) => operation(manager),
|
||||
} as unknown as DataSource;
|
||||
const service = new AuditQueryService(dataSource);
|
||||
const query = Object.assign(new ListAuditQueryDto(), {
|
||||
page: 2,
|
||||
pageSize: 25,
|
||||
});
|
||||
|
||||
const result = await service.list(query);
|
||||
assert.equal(result.meta.total, 26);
|
||||
assert.equal(result.meta.totalPages, 2);
|
||||
assert.equal(result.meta.page, 2);
|
||||
assert.equal(result.data.length, 1);
|
||||
});
|
||||
Reference in New Issue
Block a user