Skip to content

Commit cd5df45

Browse files
committed
fix: Fixed sudo requests
1 parent 7a58844 commit cd5df45

File tree

3 files changed

+60
-11
lines changed

3 files changed

+60
-11
lines changed

src/events/context.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ export const ctx = new class {
4747
return this.emitter.on(eventName, listener);
4848
}
4949

50+
once(eventName: string | symbol, listener: (...args: any[]) => void): EventEmitter {
51+
return this.emitter.once(eventName, listener);
52+
}
53+
5054
log(...args: unknown[]) {
5155
this.emitter.emit(Event.STDOUT, ...args);
5256
}

src/plugins/plugin-process.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,22 +72,23 @@ export class PluginProcess {
7272
}
7373

7474
if (message.cmd === MessageCmd.SUDO_REQUEST) {
75-
const { data } = message;
75+
const { data, requestId } = message;
7676
if (!sudoRequestValidator(data)) {
7777
throw new Error(`Invalid sudo request from plugin ${pluginName}. ${JSON.stringify(sudoRequestValidator.errors, null, 2)}`);
7878
}
7979

80-
ctx.sudoRequested(pluginName, data as unknown as SudoRequestData);
81-
}
82-
})
83-
84-
// Send out sudo granted events
85-
ctx.on(Event.SUDO_REQUEST_GRANTED, (_pluginName, data) => {
86-
if (_pluginName === pluginName) {
87-
process.send({
88-
cmd: returnMessageCmd(MessageCmd.SUDO_REQUEST),
89-
data
80+
// Send out sudo granted events
81+
ctx.once(Event.SUDO_REQUEST_GRANTED, (_pluginName, data) => {
82+
if (_pluginName === pluginName) {
83+
process.send({
84+
cmd: returnMessageCmd(MessageCmd.SUDO_REQUEST),
85+
requestId,
86+
data
87+
})
88+
}
9089
})
90+
91+
ctx.sudoRequested(pluginName, data as unknown as SudoRequestData);
9192
}
9293
})
9394
}

test/integration/sudo.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { fork } from 'node:child_process';
2+
import { type Readable } from 'node:stream';
3+
import { describe, it, expect, vi } from 'vitest';
4+
5+
import { PluginProcess, returnMessageCmd } from '../../src/plugins/plugin-process.js';
6+
import { MessageCmd, MessageStatus, SpawnStatus } from 'codify-schemas';
7+
import { ctx } from '../../src/events/context.js';
8+
9+
vi.mock('node:child_process', async () => {n
10+
const { ChildProcess } = await import('node:child_process');
11+
const { default: EventEmitter } = await import('node:events');
12+
13+
const process = new ChildProcess();
14+
process.stdout = new EventEmitter() as Readable;
15+
process.stderr = new EventEmitter() as Readable
16+
process.send = () => true;
17+
18+
return { fork: () => process };
19+
})
20+
21+
describe('Message sender tests', async () => {
22+
it('Is able to send a message and await a result', async () => {
23+
// Uses the child process from the mocks
24+
const mockChildProcess = fork('');
25+
26+
const sudoRequestedSpy = vi.spyOn(ctx, 'sudoRequested');
27+
const processSpy = vi.spyOn(mockChildProcess, 'send');
28+
29+
const plugin = await PluginProcess.start('', 'TestPlugin', false);
30+
31+
mockChildProcess.emit('message', { cmd: MessageCmd.SUDO_REQUEST, data: { command: 'sudo something' }, requestId: 'requestId' })
32+
expect(sudoRequestedSpy).toHaveBeenCalledOnce();
33+
34+
ctx.sudoRequestGranted('TestPlugin', { status: SpawnStatus.SUCCESS, data: 'success' })
35+
expect(processSpy).to.be.lastCalledWith({
36+
cmd: returnMessageCmd(MessageCmd.SUDO_REQUEST),
37+
requestId: 'requestId',
38+
data: expect.objectContaining({
39+
status: MessageStatus.SUCCESS,
40+
data: 'success',
41+
})
42+
});
43+
})
44+
});

0 commit comments

Comments
 (0)