Release v2.17.5
This commit is contained in:
1 parent
46636939de
commit
86b9609ea7
11 files changed
+285
-56
No files matched your search
@@ -7,6 +7,7 @@ const registerAuditLogRoutes = require('../src/web/routes/settings/audit-log');
|
||||
|
||||
test('audit log uses its own read permission and shared pagination partial', async () => {
|
||||
const handlers = {};
|
||||
const queries = [];
|
||||
const app = {
|
||||
get(path, ...routeHandlers) {
|
||||
handlers[path] = routeHandlers;
|
||||
@@ -15,8 +16,16 @@ test('audit log uses its own read permission and shared pagination partial', asy
|
||||
|
||||
registerAuditLogRoutes(app, {
|
||||
pool: {
|
||||
async query(sql) {
|
||||
if (String(sql).includes('FROM o_audit_events')) {
|
||||
async query(sql, params) {
|
||||
const query = String(sql);
|
||||
queries.push([query, params || []]);
|
||||
if (query.includes('SELECT COUNT(*) AS count')) {
|
||||
return [[{ count: 2 }]];
|
||||
}
|
||||
if (query.includes('SELECT DISTINCT e.event_type')) {
|
||||
return [[{ event_type: 'login.failed' }, { event_type: 'login.success' }]];
|
||||
}
|
||||
if (query.includes('FROM o_audit_events')) {
|
||||
return [[
|
||||
{
|
||||
id: 1,
|
||||
@@ -102,6 +111,12 @@ test('audit log uses its own read permission and shared pagination partial', asy
|
||||
assert.ok(response.body.indexOf('login.success') < response.body.indexOf('login.failed'));
|
||||
assert.match(response.body, />Export</);
|
||||
assert.ok(handlers['/settings/audit-log/export']);
|
||||
const pageQuery = queries.find(([sql]) => sql.includes('LIMIT ? OFFSET ?'));
|
||||
assert.ok(pageQuery);
|
||||
assert.match(pageQuery[0], /ORDER BY e\.occurred_at DESC, e\.id DESC LIMIT \? OFFSET \?/);
|
||||
assert.deepEqual(pageQuery[1].slice(-2), [25, 0]);
|
||||
assert.ok(queries.some(([sql]) => sql.includes('SELECT COUNT(*) AS count')));
|
||||
assert.ok(queries.some(([sql]) => sql.includes('SELECT DISTINCT e.event_type') && /WHERE e\.event_type IS NOT NULL/.test(sql)));
|
||||
|
||||
const exportResponse = {
|
||||
headers: {},
|
||||
@@ -114,4 +129,59 @@ test('audit log uses its own read permission and shared pagination partial', asy
|
||||
assert.match(exportResponse.headers['Content-Type'], /text\/csv/);
|
||||
assert.match(exportResponse.body, /Occurred At \(UTC\)/);
|
||||
assert.match(exportResponse.body, /login.success/);
|
||||
const exportQuery = queries.filter(([sql]) => sql.includes('FROM o_audit_events') && !sql.includes('SELECT COUNT(*)') && !sql.includes('SELECT DISTINCT')).at(-1);
|
||||
assert.ok(exportQuery);
|
||||
assert.doesNotMatch(exportQuery[0], /LIMIT \?/);
|
||||
});
|
||||
|
||||
test('audit log applies SQL filters, escaped search, and selected sort before pagination', async () => {
|
||||
const handlers = {};
|
||||
const queries = [];
|
||||
const app = {
|
||||
get(path, ...routeHandlers) {
|
||||
handlers[path] = routeHandlers;
|
||||
}
|
||||
};
|
||||
|
||||
registerAuditLogRoutes(app, {
|
||||
pool: {
|
||||
async query(sql, params) {
|
||||
const query = String(sql);
|
||||
queries.push([query, params || []]);
|
||||
if (query.includes('SELECT COUNT(*) AS count')) return [[{ count: 40 }]];
|
||||
return [[]];
|
||||
}
|
||||
},
|
||||
formatDashboardDate() {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
await handlers['/settings/audit-log'][1]({
|
||||
currentUser: { id: 7, permissions: ['audit-log.read'] },
|
||||
query: {
|
||||
category: 'Authentication',
|
||||
event_type: 'Login.Success',
|
||||
search: ' Alice%_ ',
|
||||
sort: 'actor',
|
||||
direction: 'desc',
|
||||
page: '2'
|
||||
}
|
||||
}, { send() {} }, function (error) {
|
||||
throw error;
|
||||
});
|
||||
|
||||
const countQuery = queries.find(([sql]) => sql.includes('SELECT COUNT(*) AS count'));
|
||||
const pageQuery = queries.find(([sql]) => sql.includes('LIMIT ? OFFSET ?'));
|
||||
const eventTypesQuery = queries.find(([sql]) => sql.includes('SELECT DISTINCT e.event_type'));
|
||||
assert.ok(countQuery);
|
||||
assert.ok(pageQuery);
|
||||
assert.ok(eventTypesQuery);
|
||||
assert.match(countQuery[0], /e\.category = \? AND e\.event_type = \?/);
|
||||
assert.match(countQuery[0], /LOWER\(COALESCE\(CAST\(e\.category AS CHAR\)/);
|
||||
assert.deepEqual(countQuery[1].slice(0, 2), ['authentication', 'login.success']);
|
||||
assert.ok(countQuery[1].includes('%alice\\%\\_%'));
|
||||
assert.match(pageQuery[0], /ORDER BY COALESCE\(NULLIF\(u\.name, ''\), u\.username, 'System'\) DESC, e\.occurred_at DESC, e\.id DESC/);
|
||||
assert.deepEqual(pageQuery[1].slice(-2), [25, 25]);
|
||||
assert.match(eventTypesQuery[0], /AND e\.event_type IS NOT NULL/);
|
||||
});
|
||||
Reference in new issue
Block a user