From 305b6087b0afce62edff75da33dd9de7069c19ed Mon Sep 17 00:00:00 2001 From: neon <18559658+neonsolstice@users.noreply.github.com> Date: Mon, 2 Nov 2026 02:45:38 +0000 Subject: [PATCH] fix(reader): accept underscores in KOReader device IDs Allow KOReader-generated device IDs to pass shared validation so retirement and plugin requests do not fail with HTTP 400. Fixes #1928 --- server/src/modules/koreader/dto/koreader-device-param.dto.ts | 2 +- .../modules/koreader/dto/koreader-file-pattern.dto.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/modules/koreader/dto/koreader-device-param.dto.ts b/server/src/modules/koreader/dto/koreader-device-param.dto.ts index 2cc8429b0..39a2c8a3c 100644 --- a/server/src/modules/koreader/dto/koreader-device-param.dto.ts +++ b/server/src/modules/koreader/dto/koreader-device-param.dto.ts @@ -1,6 +1,6 @@ import { IsBoolean, IsString, Matches, MaxLength, MinLength } from 'class-validator'; -export const KOREADER_DEVICE_ID_REGEX = /^[A-Za-z0-9-]{1,100}$/; +export const KOREADER_DEVICE_ID_REGEX = /^[A-Za-z0-9_-]{1,100}$/; export class KoreaderDeviceParamDto { @IsString() diff --git a/server/src/modules/koreader/dto/koreader-file-pattern.dto.test.ts b/server/src/modules/koreader/dto/koreader-file-pattern.dto.test.ts index b6908e549..7e0715c9e 100644 --- a/server/src/modules/koreader/dto/koreader-file-pattern.dto.test.ts +++ b/server/src/modules/koreader/dto/koreader-file-pattern.dto.test.ts @@ -50,8 +50,8 @@ describe('UpdateKoreaderFilePatternDto', () => { }); describe('KoreaderDeviceParamDto', () => { - it('accepts a bounded device id', async () => { - await expect(validate(plainToInstance(KoreaderDeviceParamDto, { deviceId: 'device-1' }))).resolves.toHaveLength(0); + it.each(['device-1', 'GanCao_11673992'])('accepts a bounded device id: %s', async (deviceId) => { + await expect(validate(plainToInstance(KoreaderDeviceParamDto, { deviceId }))).resolves.toHaveLength(0); }); it.each(['', 'device/one', 'device\nlog-entry', 'x'.repeat(101)])('rejects an invalid device id', async (deviceId) => {