Skip to content

Commit 1cdba5a

Browse files
fix(audit): add config flags for IP/User-Agent capture (GDPR)
Closes #3320
1 parent 24a1bec commit 1cdba5a

3 files changed

Lines changed: 44 additions & 6 deletions

File tree

modules/audit/config/audit.development.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ const config = {
22
audit: {
33
enabled: true,
44
ttlDays: 90,
5+
captureIp: true,
6+
captureUserAgent: true,
57
},
68
};
79

modules/audit/services/audit.service.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ const log = async ({ action, req, targetType, targetId, metadata } = {}) => {
3333
const oid = req.organization?._id || req.organization?.id;
3434
if (uid) entry.userId = String(uid);
3535
if (oid) entry.orgId = String(oid);
36-
entry.ip = req.ip || req.connection?.remoteAddress || '';
37-
entry.userAgent = req.headers?.['user-agent'] || '';
36+
entry.ip = config.audit?.captureIp !== false ? (req.ip || req.connection?.remoteAddress || '') : '';
37+
entry.userAgent = config.audit?.captureUserAgent !== false ? (req.headers?.['user-agent'] || '') : '';
3838
}
3939

4040
try {

modules/audit/tests/audit.service.unit.tests.js

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ jest.unstable_mockModule('../repositories/audit.repository.js', () => ({
1414
},
1515
}));
1616

17-
// Mock config
17+
// Mock config (mutable so individual tests can override flags)
18+
const mockConfig = {
19+
audit: { enabled: true, ttlDays: 90, captureIp: true, captureUserAgent: true },
20+
};
1821
jest.unstable_mockModule('../../../config/index.js', () => ({
19-
default: {
20-
audit: { enabled: true, ttlDays: 90 },
21-
},
22+
default: mockConfig,
2223
}));
2324

2425
// Mock logger to avoid winston config dependency in unit tests
@@ -46,6 +47,8 @@ describe('AuditService unit tests:', () => {
4647

4748
afterEach(() => {
4849
jest.restoreAllMocks();
50+
// Reset config to defaults
51+
mockConfig.audit = { enabled: true, ttlDays: 90, captureIp: true, captureUserAgent: true };
4952
});
5053

5154
test('should log an audit entry with request context', async () => {
@@ -111,4 +114,37 @@ describe('AuditService unit tests:', () => {
111114
await AuditService.list({ action: undefined, userId }, 1, 10);
112115
expect(mockList).toHaveBeenCalledWith({ userId }, 1, 10);
113116
});
117+
118+
// GDPR config flag tests
119+
test('should capture IP when captureIp is true (default)', async () => {
120+
mockConfig.audit = { enabled: true, ttlDays: 90, captureIp: true, captureUserAgent: true };
121+
const req = { ip: '10.0.0.1', headers: { 'user-agent': 'Bot/1.0' } };
122+
await AuditService.log({ action: 'test.ip', req });
123+
const arg = mockCreate.mock.calls[0][0];
124+
expect(arg.ip).toBe('10.0.0.1');
125+
});
126+
127+
test('should set IP to empty string when captureIp is false', async () => {
128+
mockConfig.audit = { enabled: true, ttlDays: 90, captureIp: false, captureUserAgent: true };
129+
const req = { ip: '10.0.0.1', headers: { 'user-agent': 'Bot/1.0' } };
130+
await AuditService.log({ action: 'test.ip', req });
131+
const arg = mockCreate.mock.calls[0][0];
132+
expect(arg.ip).toBe('');
133+
});
134+
135+
test('should capture User-Agent when captureUserAgent is true (default)', async () => {
136+
mockConfig.audit = { enabled: true, ttlDays: 90, captureIp: true, captureUserAgent: true };
137+
const req = { ip: '10.0.0.1', headers: { 'user-agent': 'Bot/1.0' } };
138+
await AuditService.log({ action: 'test.ua', req });
139+
const arg = mockCreate.mock.calls[0][0];
140+
expect(arg.userAgent).toBe('Bot/1.0');
141+
});
142+
143+
test('should set User-Agent to empty string when captureUserAgent is false', async () => {
144+
mockConfig.audit = { enabled: true, ttlDays: 90, captureIp: true, captureUserAgent: false };
145+
const req = { ip: '10.0.0.1', headers: { 'user-agent': 'Bot/1.0' } };
146+
await AuditService.log({ action: 'test.ua', req });
147+
const arg = mockCreate.mock.calls[0][0];
148+
expect(arg.userAgent).toBe('');
149+
});
114150
});

0 commit comments

Comments
 (0)