mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
118 lines
3.3 KiB
TypeScript
118 lines
3.3 KiB
TypeScript
|
import {IAuditLogger} from 'app/server/lib/AuditLogger';
|
||
|
import {LogMethods} from 'app/server/lib/LogMethods';
|
||
|
import {assert} from 'chai';
|
||
|
import moment from 'moment-timezone';
|
||
|
import nock from 'nock';
|
||
|
import * as sinon from 'sinon';
|
||
|
import {TestServer} from 'test/gen-server/apiUtils';
|
||
|
import * as testUtils from 'test/server/testUtils';
|
||
|
|
||
|
describe('GristAuditLogger', function() {
|
||
|
let auditLogger: IAuditLogger;
|
||
|
let oldEnv: testUtils.EnvironmentSnapshot;
|
||
|
let server: TestServer;
|
||
|
|
||
|
before(async function() {
|
||
|
oldEnv = new testUtils.EnvironmentSnapshot();
|
||
|
process.env.GRIST_AUDIT_HTTP_ENDPOINT = 'https://api.getgrist.com/events';
|
||
|
process.env.GRIST_AUDIT_HTTP_AUTHORIZATION_HEADER = 'Grist bb48d1f8-8f6c-4065-8951-8543a8e70597';
|
||
|
server = new TestServer(this);
|
||
|
await server.start();
|
||
|
auditLogger = server.server.getAuditLogger();
|
||
|
});
|
||
|
|
||
|
after(async function() {
|
||
|
await server.stop();
|
||
|
oldEnv.restore();
|
||
|
});
|
||
|
|
||
|
describe('logEventAsync', function() {
|
||
|
const sandbox: sinon.SinonSandbox = sinon.createSandbox();
|
||
|
let logErrorCallArguments: any[] = [];
|
||
|
|
||
|
before(async function() {
|
||
|
sandbox
|
||
|
.stub(LogMethods.prototype, 'error')
|
||
|
.callsFake((...args) => logErrorCallArguments.push([...args]));
|
||
|
});
|
||
|
|
||
|
after(async function() {
|
||
|
sandbox.restore();
|
||
|
});
|
||
|
|
||
|
afterEach(function() {
|
||
|
logErrorCallArguments = [];
|
||
|
nock.cleanAll();
|
||
|
});
|
||
|
|
||
|
it('logs audit events', async function() {
|
||
|
const timestamp = moment().toISOString();
|
||
|
const scope = nock('https://api.getgrist.com')
|
||
|
.matchHeader('Authorization', 'Grist bb48d1f8-8f6c-4065-8951-8543a8e70597')
|
||
|
.post('/events', {
|
||
|
event: {
|
||
|
name: 'createDocument',
|
||
|
user: null,
|
||
|
details: {
|
||
|
id: 'docId',
|
||
|
},
|
||
|
},
|
||
|
timestamp,
|
||
|
})
|
||
|
.reply(200);
|
||
|
await assert.isFulfilled(
|
||
|
auditLogger.logEventAsync(null, {
|
||
|
event: {
|
||
|
name: 'createDocument',
|
||
|
details: {id: 'docId'},
|
||
|
},
|
||
|
timestamp,
|
||
|
})
|
||
|
);
|
||
|
assert.isTrue(scope.isDone());
|
||
|
});
|
||
|
|
||
|
it('throws on failure to log', async function() {
|
||
|
nock('https://api.getgrist.com')
|
||
|
.post('/events')
|
||
|
.reply(404, 'Not found');
|
||
|
await assert.isRejected(
|
||
|
auditLogger.logEventAsync(null, {
|
||
|
event: {
|
||
|
name: 'createDocument',
|
||
|
details: {id: 'docId'},
|
||
|
},
|
||
|
}),
|
||
|
'received a non-200 response from https://api.getgrist.com/events: 404 Not found'
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('throws if max pending requests exceeded', async function() {
|
||
|
nock('https://api.getgrist.com')
|
||
|
.persist()
|
||
|
.post('/events')
|
||
|
.delay(2000)
|
||
|
.reply(200);
|
||
|
// Queue up enough pending requests to reach the limit (25).
|
||
|
for (let i = 0; i < 25; i++) {
|
||
|
void auditLogger.logEvent(null, {
|
||
|
event: {
|
||
|
name: 'createDocument',
|
||
|
details: {id: 'docId'},
|
||
|
},
|
||
|
});
|
||
|
}
|
||
|
await assert.isRejected(
|
||
|
auditLogger.logEventAsync(null, {
|
||
|
event: {
|
||
|
name: 'createDocument',
|
||
|
details: {id: 'docId'},
|
||
|
},
|
||
|
}),
|
||
|
'exceeded the maximum number of pending audit event calls (25)'
|
||
|
);
|
||
|
nock.abortPendingRequests();
|
||
|
});
|
||
|
});
|
||
|
});
|