Skip to content

Commit 618f939

Browse files
committed
refactor(api/powerOn): use common validator for deviceId
1 parent a031098 commit 618f939

File tree

2 files changed

+41
-13
lines changed

2 files changed

+41
-13
lines changed

api/src/services/power/powerOn.test.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import { FastifyReply } from 'fastify/types/reply';
12
import globalMocks from '../../../config/jest/globalMocks';
23
import resetMocks from '../../../config/jest/resetMocks';
34
import { replyWithInternalError, replyWithItemNotFound, replyWithJson } from '../../common/api';
45
import { AppContext } from '../../common/context';
5-
import { getMockedFastifyReply } from '../../helpers/testing/mockObjects';
6+
import { getDefaultDeviceConfig, getMockedFastifyReply } from '../../helpers/testing/mockObjects';
67
import { PowerStatus } from '../../models/common';
8+
import { DeviceConfig } from '../../models/configuration';
9+
import { validateDeviceIdentifier } from '../common/validators';
710
import { powerOnForDevice, powerOnForDevicesScheduled } from './powerOn';
811

912
import type { WakeOptions } from 'wake_on_lan';
@@ -13,25 +16,30 @@ const { wakeonlanMock } = globalMocks;
1316
jest.mock('../../common/api');
1417
jest.mock('../../common/logger', () => ({
1518
coreLogger: {
19+
error: jest.fn(),
1620
info: jest.fn(),
1721
},
1822
}));
23+
jest.mock('../common/validators');
1924

2025
const replyWithJsonMock = replyWithJson as jest.Mock;
2126
const replyWithInternalErrorMock = replyWithInternalError as jest.Mock;
2227
const replyWithItemNotFoundMock = replyWithItemNotFound as jest.Mock;
28+
const validateDeviceIdentifierMock = validateDeviceIdentifier as jest.Mock<DeviceConfig | undefined, [string, FastifyReply?]>;
2329

2430
beforeEach(() => {
2531
wakeonlanMock.wake.mockImplementation((_a, _o, cb) => {
2632
cb();
27-
});
33+
});
34+
validateDeviceIdentifierMock.mockReturnValue(getDefaultDeviceConfig());
2835
});
2936

3037
afterEach(() => {
3138
resetMocks();
3239
replyWithJsonMock.mockReset();
3340
replyWithInternalErrorMock.mockReset();
3441
replyWithItemNotFoundMock.mockReset();
42+
validateDeviceIdentifierMock.mockReset();
3543
});
3644

3745
describe('powerOn service', () => {
@@ -86,12 +94,16 @@ describe('powerOn service', () => {
8694
});
8795

8896
it('should return 404 when device is not found', async () => {
89-
// given-when
97+
// given
98+
validateDeviceIdentifierMock.mockReturnValue(undefined);
99+
100+
// when
90101
await powerOnForDevice('foo', defaultReply);
91102

92103
// then
93104
expect(wakeonlanMock.wake).not.toHaveBeenCalled();
94-
expect(replyWithItemNotFoundMock).toHaveBeenCalledWith(defaultReply, 'deviceId', 'foo');
105+
expect(replyWithJsonMock).not.toHaveBeenCalled();
106+
expect(replyWithItemNotFoundMock).not.toHaveBeenCalled();
95107
});
96108

97109
it('should not attempt to wake device nor update diags context and return 204 when already powered ON', async () => {
@@ -123,5 +135,16 @@ describe('powerOn service', () => {
123135
expect(lastStartAttempt.reason).toBe('scheduled');
124136
expect(wakeonlanMock.wake).toHaveBeenCalledTimes(1);
125137
});
138+
139+
it('should handle invalid device identifier', async () => {
140+
// given
141+
validateDeviceIdentifierMock.mockReturnValue(undefined);
142+
143+
// when
144+
await powerOnForDevicesScheduled(['0']);
145+
146+
// then
147+
expect(wakeonlanMock.wake).not.toHaveBeenCalled();
148+
});
126149
});
127150
});

api/src/services/power/powerOn.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type { DeviceConfig } from '../../models/configuration';
1212
import { ApiItem } from '../../models/api';
1313
import { PowerStatus } from '../../models/common';
1414
import { LastPowerAttemptReason } from '../../processors/diag/models/diag';
15+
import { validateDeviceIdentifier } from '../common/validators';
1516

1617
/**
1718
* Power->ON service implementation: for a specified device
@@ -20,17 +21,20 @@ export async function powerOnForDevice(deviceId: string, reply: FastifyReply) {
2021
const { log: logger } = reply;
2122

2223
try {
23-
await powerOnForDeviceBase(deviceId, logger, LastPowerAttemptReason.API);
24+
await powerOnForDeviceBase(deviceId, logger, LastPowerAttemptReason.API, reply);
2425
replyWithJson(reply);
2526
} catch (error) {
2627
if (error === ERROR_DEVICE_NOT_FOUND) {
27-
replyWithItemNotFound(reply, ApiItem.DEVICE_ID, deviceId);
28-
} else if (error === ERROR_NOOP) {
28+
return;
29+
}
30+
31+
if (error === ERROR_NOOP) {
2932
replyWithJson(reply);
3033
} else {
3134
// WOL error
3235
replyWithInternalError(reply, `Unable to perform wake on LAN: ${error}`);
3336
}
37+
3438
return;
3539
}
3640
}
@@ -45,20 +49,21 @@ export async function powerOnForDevicesScheduled(deviceIds: string[]) {
4549
try {
4650
await Promise.all(powerOnPromises);
4751
} catch (error) {
48-
coreLogger.error('(powerOnForDevicesScheduled) error when attempting scheduled power ON operation');
52+
coreLogger.error('(powerOnForDevicesScheduled) error when attempting scheduled power ON operation: %s');
4953
}
5054
}
5155

52-
async function powerOnForDeviceBase(deviceId: string, logger: FastifyBaseLogger, reason: LastPowerAttemptReason) {
53-
const deviceConfig = getDeviceConfig(deviceId);
56+
async function powerOnForDeviceBase(deviceId: string, logger: FastifyBaseLogger, reason: LastPowerAttemptReason, reply?: FastifyReply) {
57+
const deviceConfig = validateDeviceIdentifier(deviceId, reply);
5458
if (!deviceConfig) {
59+
logger.error('(powerOn::powerOnForDeviceBase) Device not found: %s', deviceId);
5560
throw ERROR_DEVICE_NOT_FOUND;
5661
}
5762

5863
// No need to power on device if its power status is ON already
5964
const deviceDiagContext = AppContext.get().diagnostics[deviceId];
6065
if (deviceDiagContext?.power.state === PowerStatus.ON) {
61-
logger.info(`(powerOn::powerOnForDeviceBase) NOOP serverId:${deviceId}`);
66+
logger.info('(powerOn::powerOnForDeviceBase) NOOP deviceId: %s', deviceId);
6267
throw ERROR_NOOP;
6368
}
6469

@@ -71,9 +76,9 @@ async function powerOnForDeviceBase(deviceId: string, logger: FastifyBaseLogger,
7176
try {
7277
await awakeDevice(deviceConfig);
7378

74-
logger.info(`(powerOn::powerOnForDeviceBase) OK serverId:${deviceId}`);
79+
logger.info('(powerOn::powerOnForDeviceBase) OK deviceId: %s', deviceId);
7580
} catch (wolError) {
76-
logger.error(`(powerOn::powerOnForDeviceBase) KO serverId:${deviceId}-${wolError}`);
81+
logger.error('(powerOn::powerOnForDeviceBase) KO deviceId: %s - %s', deviceId, wolError);
7782
throw wolError;
7883
}
7984
}

0 commit comments

Comments
 (0)