fix(audit): expand tilde paths for audit log output
This commit is contained in:
@@ -0,0 +1,49 @@
|
|||||||
|
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'fs';
|
||||||
|
import { homedir, tmpdir } from 'os';
|
||||||
|
import { join, resolve } from 'path';
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { AuditLogger } from './logger.js';
|
||||||
|
|
||||||
|
describe('AuditLogger', () => {
|
||||||
|
it('expands ~ in audit path before writing logs', async () => {
|
||||||
|
const previousHome = process.env.HOME;
|
||||||
|
const tempHome = mkdtempSync(join(tmpdir(), 'flynn-audit-home-'));
|
||||||
|
process.env.HOME = tempHome;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Sanity-check this process sees the temp home.
|
||||||
|
expect(homedir()).toBe(tempHome);
|
||||||
|
|
||||||
|
const logger = new AuditLogger({
|
||||||
|
enabled: true,
|
||||||
|
path: '~/.local/share/flynn/audit.log',
|
||||||
|
max_size_mb: 10,
|
||||||
|
keep_days: 30,
|
||||||
|
levels: {
|
||||||
|
tools: 'debug',
|
||||||
|
sessions: 'debug',
|
||||||
|
automation: 'debug',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
logger.systemStart('test-component');
|
||||||
|
await logger.close();
|
||||||
|
await new Promise((resolvePromise) => setTimeout(resolvePromise, 25));
|
||||||
|
|
||||||
|
const loggerPath = (logger as unknown as { config: { path: string } }).config.path;
|
||||||
|
const expectedPath = resolve(tempHome, '.local/share/flynn/audit.log');
|
||||||
|
expect(loggerPath).toBe(expectedPath);
|
||||||
|
expect(existsSync(expectedPath)).toBe(true);
|
||||||
|
const content = readFileSync(expectedPath, 'utf-8');
|
||||||
|
expect(content).toContain('"event_type":"system.start"');
|
||||||
|
expect(content).toContain('"component":"test-component"');
|
||||||
|
} finally {
|
||||||
|
if (previousHome === undefined) {
|
||||||
|
delete process.env.HOME;
|
||||||
|
} else {
|
||||||
|
process.env.HOME = previousHome;
|
||||||
|
}
|
||||||
|
rmSync(tempHome, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
+15
-4
@@ -1,5 +1,6 @@
|
|||||||
import { createWriteStream, existsSync, mkdirSync } from 'fs';
|
import { createWriteStream, existsSync, mkdirSync } from 'fs';
|
||||||
import { dirname } from 'path';
|
import { dirname, resolve } from 'path';
|
||||||
|
import { homedir } from 'os';
|
||||||
import type {
|
import type {
|
||||||
AuditEvent,
|
AuditEvent,
|
||||||
AuditConfig,
|
AuditConfig,
|
||||||
@@ -41,8 +42,11 @@ export class AuditLogger {
|
|||||||
private rotator: AuditRotator;
|
private rotator: AuditRotator;
|
||||||
|
|
||||||
constructor(config: AuditConfig) {
|
constructor(config: AuditConfig) {
|
||||||
this.config = config;
|
this.config = {
|
||||||
this.rotator = new AuditRotator(config);
|
...config,
|
||||||
|
path: expandPath(config.path),
|
||||||
|
};
|
||||||
|
this.rotator = new AuditRotator(this.config);
|
||||||
|
|
||||||
if (!this.config.enabled) {
|
if (!this.config.enabled) {
|
||||||
return;
|
return;
|
||||||
@@ -50,7 +54,7 @@ export class AuditLogger {
|
|||||||
|
|
||||||
this.ensureLogDirectory();
|
this.ensureLogDirectory();
|
||||||
this.rotator.checkRotation();
|
this.rotator.checkRotation();
|
||||||
this.writeStream = createWriteStream(config.path, { flags: 'a' });
|
this.writeStream = createWriteStream(this.config.path, { flags: 'a' });
|
||||||
}
|
}
|
||||||
|
|
||||||
private ensureLogDirectory(): void {
|
private ensureLogDirectory(): void {
|
||||||
@@ -357,3 +361,10 @@ export class AuditLogger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function expandPath(p: string): string {
|
||||||
|
if (p.startsWith('~/') || p === '~') {
|
||||||
|
return resolve(homedir(), p.slice(2));
|
||||||
|
}
|
||||||
|
return resolve(p);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user