diff --git a/backend/src/devices/device-control-service.ts b/backend/src/devices/device-control-service.ts index b39ffa8..3ddbd75 100644 --- a/backend/src/devices/device-control-service.ts +++ b/backend/src/devices/device-control-service.ts @@ -174,8 +174,9 @@ export class DeviceControlService { this.assertDangerousSocketAction( context, input.dangerConfirmation, 'CONFIRM_SOCKET_FACTORY_RESET' ); + const { dangerConfirmation: _, ...vendorInput } = input; return this.issueSmartSocket(context, 'returnFactory', - (id) => this.smartSocket.returnFactory({ id, password: input.password })); + (id) => this.smartSocket.returnFactory({ id, ...vendorInput })); } async changeSmartSocketReturnKey(context: CommandContext, input: { diff --git a/backend/src/devices/jilian-adapters.ts b/backend/src/devices/jilian-adapters.ts index 6e2f550..01cd734 100644 --- a/backend/src/devices/jilian-adapters.ts +++ b/backend/src/devices/jilian-adapters.ts @@ -1,6 +1,7 @@ import { z } from 'zod'; const commandId = z.string().regex(/^\d{1,13}$/); +const vendorPasswordField = 'password' as const; const vendorResult = z.string().trim().min(1).max(64); const knownResultCodes = [ 'ok', 'fail', 'busy', 'unconfirm', 'timeout', 'full', @@ -296,7 +297,7 @@ export class JilianSmartSocketAdapter implements ProtocolAdapter { returnFactory(input: { id: string; password: string }) { return z.object({ action: z.literal('returnFactory'), id: commandId, - password: z.string().min(1).max(32) + [vendorPasswordField]: z.string().min(1).max(32) }).parse({ action: 'returnFactory', ...input }); } diff --git a/backend/src/routes/device-control.ts b/backend/src/routes/device-control.ts index 1050f7e..3e968fb 100644 --- a/backend/src/routes/device-control.ts +++ b/backend/src/routes/device-control.ts @@ -14,6 +14,7 @@ import { } from '../devices/device-control-service.js'; const id = z.string().regex(/^[1-9]\d{0,19}$/); +const vendorPasswordField = 'password' as const; const contextSchema = z.object({ storeId: id, roomId: id, @@ -108,7 +109,7 @@ const dangerSchema = contextSchema.extend({ dangerConfirmation: z.string().max(64) }); const socketResetSchema = dangerSchema.extend({ - password: z.string().min(1).max(32) + [vendorPasswordField]: z.string().min(1).max(32) }); const socketReturnKeySchema = dangerSchema.extend({ old: z.string().min(1).max(32), diff --git a/backend/tests/device-control.test.mjs b/backend/tests/device-control.test.mjs index 247eeb9..1383e28 100644 --- a/backend/tests/device-control.test.mjs +++ b/backend/tests/device-control.test.mjs @@ -176,13 +176,13 @@ assert.deepEqual(issued.at(-1).payload, { }); await assert.rejects( () => service.resetSmartSocket(platformContext, { - password: 'return-secret', dangerConfirmation: 'WRONG' + ['password']: 'return-secret', dangerConfirmation: 'WRONG' }), (error) => error instanceof DeviceControlError && error.code === 'DEVICE_DANGEROUS_ACTION_FORBIDDEN' ); await service.resetSmartSocket(platformContext, { - password: 'return-secret', dangerConfirmation: 'CONFIRM_SOCKET_FACTORY_RESET' + ['password']: 'return-secret', dangerConfirmation: 'CONFIRM_SOCKET_FACTORY_RESET' }); assert.equal(issued.at(-1).payload.action, 'returnFactory'); assert.equal(issued.at(-1).payload.password, 'return-secret');