83 lines
4.0 KiB
TypeScript
83 lines
4.0 KiB
TypeScript
import { ForbiddenException } from '@nestjs/common';
|
|||
|
|
import { vi } from 'vitest';
|
||
|
|
import type { AuditService } from '../audit/audit.service.js';
|
||
|
|
import type { AuthUser } from '../auth/auth.types.js';
|
||
|
|
import type { PermissionsService } from '../permissions/permissions.service.js';
|
||
|
|
import type { SapClientService } from '../sap/sap-client.service.js';
|
||
|
|
import { SlProxyService } from './sl-proxy.service.js';
|
||
|
|
|
||
|
|
const user: AuthUser = { webUser: 'ana', empId: 7, firstName: 'Ana', lastName: 'P' };
|
||
|
|
|
||
|
|
describe('SlProxyService: auditoría', () => {
|
||
|
|
let request: ReturnType<typeof vi.fn>;
|
||
|
|
let record: ReturnType<typeof vi.fn>;
|
||
|
|
let paths: string[];
|
||
|
|
let service: SlProxyService;
|
||
|
|
|
||
|
|
beforeEach(() => {
|
||
|
|
request = vi.fn(async () => ({ data: { DocEntry: 316, DocNum: 12 } }));
|
||
|
|
record = vi.fn(async () => undefined);
|
||
|
|
paths = ['*'];
|
||
|
|
service = new SlProxyService(
|
||
|
|
{ request } as unknown as SapClientService,
|
||
|
|
{ getPaths: async () => paths } as unknown as PermissionsService,
|
||
|
|
{ record } as unknown as AuditService,
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('crear queda registrado con la clave creada y solo los nombres de los campos', async () => {
|
||
|
|
await service.create(user, 'Orders', { CardCode: 'C1', Comments: 'privado', DocumentLines: [{ ItemCode: 'A' }, { ItemCode: 'B' }] }, {}, '10.0.0.5');
|
||
|
|
expect(record).toHaveBeenCalledWith({
|
||
|
|
action: 'sl_create',
|
||
|
|
webUser: 'ana',
|
||
|
|
ip: '10.0.0.5',
|
||
|
|
resource: 'Orders',
|
||
|
|
key: '316',
|
||
|
|
detail: { fields: ['CardCode', 'Comments'], collections: { DocumentLines: 2 } },
|
||
|
|
});
|
||
|
|
expect(JSON.stringify(record.mock.calls)).not.toContain('privado');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('modificar queda registrado con su clave y los campos tocados', async () => {
|
||
|
|
request.mockResolvedValueOnce({ data: undefined });
|
||
|
|
await service.update(user, 'BusinessPartners', 'C100', { Phone1: '123' }, {}, '10.0.0.5');
|
||
|
|
expect(record).toHaveBeenCalledWith({ action: 'sl_update', webUser: 'ana', ip: '10.0.0.5', resource: 'BusinessPartners', key: 'C100', detail: { fields: ['Phone1'] } });
|
||
|
|
});
|
||
|
|
|
||
|
|
it('si SAP rechaza la operación queda registrada como error, con el mensaje, y el error sigue su camino', async () => {
|
||
|
|
request.mockRejectedValueOnce(new Error('1250000110 - RUT is missing'));
|
||
|
|
await expect(service.create(user, 'BusinessPartners', { CardCode: 'C9' }, {}, '10.0.0.5')).rejects.toThrow('RUT is missing');
|
||
|
|
expect(record).toHaveBeenCalledWith({
|
||
|
|
action: 'sl_create',
|
||
|
|
webUser: 'ana',
|
||
|
|
ip: '10.0.0.5',
|
||
|
|
resource: 'BusinessPartners',
|
||
|
|
outcome: 'error',
|
||
|
|
detail: { fields: ['CardCode'], error: '1250000110 - RUT is missing' },
|
||
|
|
});
|
||
|
|
request.mockRejectedValueOnce(new Error('412'));
|
||
|
|
await expect(service.update(user, 'Orders', '5', { Comments: 'x' }, {}, '10.0.0.5')).rejects.toThrow('412');
|
||
|
|
expect(record).toHaveBeenLastCalledWith(expect.objectContaining({ action: 'sl_update', key: '5', outcome: 'error' }));
|
||
|
|
});
|
||
|
|
|
||
|
|
it('un usuario sin permiso de escritura queda registrado como denegado y no llega a SAP', async () => {
|
||
|
|
paths = ['/ventas/ordenes'];
|
||
|
|
await expect(service.create(user, 'Invoices', { CardCode: 'C1' }, {}, '10.0.0.5')).rejects.toBeInstanceOf(ForbiddenException);
|
||
|
|
expect(request).not.toHaveBeenCalled();
|
||
|
|
expect(record).toHaveBeenCalledWith({ action: 'sl_denied', webUser: 'ana', ip: '10.0.0.5', resource: 'Invoices', outcome: 'denied', detail: { method: 'POST' } });
|
||
|
|
});
|
||
|
|
|
||
|
|
it('las acciones de solo consulta (series de numeración) no se auditan', async () => {
|
||
|
|
request.mockResolvedValueOnce({ data: { value: [] } });
|
||
|
|
await service.create(user, 'SeriesService_GetDocumentSeries', { DocumentTypeParams: { Document: '17' } }, {}, '10.0.0.5');
|
||
|
|
expect(record).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('las lecturas no se auditan', async () => {
|
||
|
|
request.mockResolvedValueOnce({ data: { value: [] } });
|
||
|
|
await service.list(user, 'Orders', {}, {});
|
||
|
|
request.mockResolvedValueOnce({ data: {} });
|
||
|
|
await service.get(user, 'Orders', '5', {});
|
||
|
|
expect(record).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
});
|