mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-08 08:29:42 +02:00
feat(remote): host-unreachable banner, manual wake, and native MAC wake-on-LAN
The reactive wake (typing into a session whose host slept) left the state invisible: nothing told the user the machine was asleep, and with no wake target configured there was nothing to do about it. Adds: - RemoteHost.wakeMac (comma-separated) - Codeman builds and broadcasts the magic packet itself (UDP port 9), so the common case needs no external script. The existing wakeCommand stays as the explicit override. - GET /api/sessions/:id/reachability - probes (throttled, cached, and it never wakes) and reports HOW the host can be woken, or that nothing is configured. - POST /api/sessions/:id/wake - wakes, waits, reattaches the pane and flushes buffered input; 400 with a routable message when no target is configured. - The amber host-unreachable banner + its 'Wake' / 'Configure WoL' action, and a small config dialog that saves via PUT /api/remote-hosts/:id. - RemoteWakeDeps.resolveRemote: host config is re-resolved for LIVE sessions (throttled + cached), so saving the dialog takes effect without a restart.
This commit is contained in:
@@ -115,6 +115,15 @@ describe('remote-hosts domain', () => {
|
||||
expect(RemoteHostSchema.safeParse({ ...host, wakeCommand: '/bin/sh$(id)' }).success).toBe(false);
|
||||
expect(RemoteHostSchema.safeParse({ ...host, wakeCommand: '/bin/`id`' }).success).toBe(false);
|
||||
});
|
||||
|
||||
it('accepts one or more MAC addresses and rejects anything else', () => {
|
||||
expect(RemoteHostSchema.safeParse({ ...host, wakeMac: '04:d9:f5:80:c6:58' }).success).toBe(true);
|
||||
expect(RemoteHostSchema.safeParse({ ...host, wakeMac: '04-d9-f5-80-c6-58, 1C:61:B4:20:58:EB' }).success).toBe(
|
||||
true
|
||||
);
|
||||
expect(RemoteHostSchema.safeParse({ ...host, wakeMac: '04:d9:f5:80:c6' }).success).toBe(false);
|
||||
expect(RemoteHostSchema.safeParse({ ...host, wakeMac: '04:d9:f5:80:c6:58; rm -rf /' }).success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('rehydrateRemoteHostFields', () => {
|
||||
@@ -152,6 +161,15 @@ describe('remote-hosts domain', () => {
|
||||
expect(rehydrateRemoteHostFields(remote, hosts())?.wakeCommand).toBeUndefined();
|
||||
});
|
||||
|
||||
it('refreshes a MAC that only exists in the host config', () => {
|
||||
const withMac = new Map(
|
||||
hosts()
|
||||
.entries()
|
||||
.map(([id, host]) => [id, { ...host, wakeMac: '04:d9:f5:80:c6:58' }] as const)
|
||||
);
|
||||
expect(rehydrateRemoteHostFields(persisted, withMac)?.wakeMac).toBe('04:d9:f5:80:c6:58');
|
||||
});
|
||||
|
||||
it('leaves the block untouched when the host is gone or the session is local', () => {
|
||||
expect(rehydrateRemoteHostFields(persisted, new Map())).toBe(persisted);
|
||||
expect(rehydrateRemoteHostFields(undefined, hosts('/x'))).toBeUndefined();
|
||||
|
||||
Reference in New Issue
Block a user