diff --git a/gas/Code.gs b/gas/Code.gs index 73ff88e..cc44979 100644 --- a/gas/Code.gs +++ b/gas/Code.gs @@ -501,10 +501,17 @@ function writeReport(reportData, clientId, recaptchaToken) { if (!studentId || !/^[a-zA-Z][0-9]{7}$/.test(studentId)) { return { success: false, error: 'VALIDATION_STUDENT_ID_FORMAT' }; } - if (!roomNumber || !/^[A-Za-z0-9-]{1,8}$/.test(roomNumber)) { + // ⚠️ 修正(BUG-ROOM-01):原本 /^[A-Za-z0-9-]{1,8}$/ 過於寬鬆, + // 允許純數字(如 "229")繞過前端驗證直接寫入試算表。 + // 現改為與 report.js 前端驗證完全一致: + // 必須以 H、I、G、FA~FF 開頭,後接 1~4 位數字,可選一個連字號再接數字。 + if (!roomNumber || !/^(H|I|G|F[ABCDEF])[0-9]{1,4}(-[0-9]+)?$/i.test(roomNumber)) { return { success: false, error: 'VALIDATION_ROOM_FORMAT' }; } - if (!bedNumber || !/^[0-9]{1,3}$/.test(bedNumber)) { + // ⚠️ 修正(BUG-BED-01):原本 /^[0-9]{1,3}$/ 允許 1~3 位數字, + // 而前端 report.js 僅允許 1 位數字(/^[0-9]$/),造成前後端不一致。 + // 改為與前端一致:僅允許單一位數字(0~9)。 + if (!bedNumber || !/^[0-9]$/.test(bedNumber)) { return { success: false, error: 'VALIDATION_BED_FORMAT' }; } if (!phone || !/^[0-9]{10}$/.test(phone)) { diff --git a/test/gas-code.test.js b/test/gas-code.test.js index dd122d5..e1c8b38 100644 --- a/test/gas-code.test.js +++ b/test/gas-code.test.js @@ -174,7 +174,7 @@ function validReportPayload() { return { studentId: 'D1234567', name: '王小明', - roomNumber: 'A101', + roomNumber: 'H101', // 修正:A 開頭不合法,改為合法的 H 前綴(BUG-ROOM-01 對齊) bedNumber: '2', phone: '0912345678', repairTime: '18:00–21:00', diff --git a/test/validation.test.js b/test/validation.test.js index f5903ad..9d1ec0a 100644 --- a/test/validation.test.js +++ b/test/validation.test.js @@ -16,7 +16,8 @@ function validatePhone(phone) { function validateBedNumber(bed) { if (!bed || typeof bed !== 'string') return false; - return /^[0-9]{1,3}$/.test(bed.trim()); + // 修正(BUG-BED-01):對齊後端 Code.gs 與前端 report.js,僅允許單一位數字 + return /^[0-9]$/.test(bed.trim()); } test('Student ID validation (1 letter + 7 digits)', () => { @@ -35,10 +36,12 @@ test('Phone validation (10 digits)', () => { assert.equal(validatePhone('abc0912345'), false, 'Letters in phone should fail'); }); -test('Bed number validation (1-3 digits)', () => { +test('Bed number validation (1 digit only)', () => { assert.equal(validateBedNumber('1'), true, '1 digit'); - assert.equal(validateBedNumber('12'), true, '2 digits'); - assert.equal(validateBedNumber('123'), true, '3 digits'); + assert.equal(validateBedNumber('9'), true, 'single digit 9'); + assert.equal(validateBedNumber('0'), true, 'single digit 0'); + assert.equal(validateBedNumber('12'), false, '2 digits should fail (front+backend now consistent)'); + assert.equal(validateBedNumber('123'), false, '3 digits should fail (front+backend now consistent)'); assert.equal(validateBedNumber('1234'), false, '4 digits should fail'); assert.equal(validateBedNumber('A'), false, 'Non-digits should fail'); });