#history#permission#rights
ภาพรวม
สิทธิ์เมนูแบบ C# (Read/Add/Edit/Delete/Admin) ถูกบังคับที่ backend เป็นระยะ 2026-10-19 .. 2026-10-29 แต่ละรอบพบประตูที่ยังไม่ตรวจสิทธิ์: route /process, SQL เขียนตรง, สิทธิ์ข้ามฐาน, ปุ่มบนจอ, คลัง/ชั้นเก็บ, รายงาน Custom SQL
อาการ
- P1 (2c273e19):
/processไม่ตรวจสิทธิ์เมนู และจอกำหนดสิทธิ์กลุ่ม/ผู้ใช้เซฟจริงไม่ได้ (ตามข้อความ commit) - P2 (5f188fc3, dbd2ef35, 0d77e6fb): ผู้มีแค่ Add เรียก
trans/saveแก้เอกสารเดิมได้ (เดิมเป็น write = Add หรือ Edit); routebarcode/formatเดียวทั้งดู/เซฟ/ลบ;/query/execเขียนตารางใน allow-list โดยไม่ดู Add/Edit/Delete - P3 (a264a99a): สิทธิ์ที่เซฟของรหัสผู้ใช้หนึ่งปนกันข้ามฐานข้อมูล (workspace) ของ provider เดียวกัน
- P4 (6cb904f7, a67dc5f0): ปุ่ม "+" ไอคอนล้วน ดินสอ ดับเบิลคลิก Insert F12 ข้ามเช็กสิทธิ์ที่ผูกกับข้อความปุ่ม; เมนูเฉพาะผู้ดูแลยังเปิดได้
- P5 (720536ab, 1b79fbc9, 13f953cc):
erp_option.perm_wh_shelfไม่ถูกใช้กับรายการเลือกคลัง/ยอดคงเหลือ/รายงานสต็อก/ref-import และผู้มีสิทธิ์ Read รันรายงาน Custom SQL อ่านตารางตรงได้
สาเหตุ (root cause)
- P1: ไม่มีชั้น
RequireRightตามชนิดการกระทำ - P2: สิทธิ์ผูกกับ route ไม่ผูกกับ "ใหม่/แก้" ใน body; ประตูเขียนบานที่สอง (query/exec, blob) ไม่มีการ์ด
- P3: การค้นหา
image_fileไม่กรองdatabase_name - P4: จอเช็กจากข้อความปุ่ม ไม่มี state สิทธิ์ต่อแท็บ; backend คุมตามชนิดการกระทำ ไม่คุมต่อจอ
- P5: C# กรองที่ lookup/ค่าเริ่มต้น ยังไม่ port; Custom SQL อ่านตารางตรง ข้ามกฎรายผู้ใช้
วิธีแก้
- P1:
RequireRight(loader, need)คืน 403 ข้อความไทย;routeRightsต่อgroup/action; route ที่ไม่อยู่ใน map = Admin (fail-closed); สิทธิ์ผู้ใช้กับกลุ่ม OR กัน เก็บ JSON ในimage_fileและอ่าน XML เดิมได้ - P2:
itemmaster/save,trans/save,doc/save,pointdocsave,stockbeginningsave:isNew=> Add ไม่ใช่ => Edit (peekJSON);barcode/formatดูaction;QueryRequiredRightแปลง verb SQL เป็น Add/Edit/Delete,/blob/insert= write - P3: กรอง
database_name IN (db, '')ใช้แถวที่ตรงฐานก่อน (DISTINCT ON) - P4:
TabsContext.screenRights+useScreenRights()จาก/api/workspace/my-screen-rightsซ่อน/ปิดปุ่มและกันเซฟ;ADMIN_ONLY_MENU_SETกรองเมนูที่ proxy workspace - P5:
applyPermWhShelfกรอง lookup,WarehousePickAllowed/WarehousePermFilter(รวม ref-import); รายงานที่permGuardedปฏิเสธ Custom SQL และ fail-closed เมื่ออ่านสิทธิ์ไม่ได้;report/run|pdfที่มีcustomSqlต้อง Admin พร้อมขยายคำต้องห้าม
commit ที่เกี่ยวข้อง
2c273e19—RequireRightบน/process+ จอบันทึกสิทธิ์ (2026-10-19)5f188fc3—trans/saveแยก Add/Edit ตาม isNew (2026-10-21)dbd2ef35—barcode/formatแยกสิทธิ์ตาม action (2026-10-22)720536ab,1b79fbc9— perm_wh_shelf กับ lookup, สต็อก, รายงาน (2026-10-22)a264a99a— สิทธิ์แยกตามdatabase_name(2026-10-24 11:00)0d77e6fb— Add/Edit/Delete บน/query/exec|execBatch|blob/insert(2026-10-24 11:08)6cb904f7—screenRightsในจอ shared (2026-10-24)a67dc5f0— เมนู admin-only (2026-10-25)13f953cc— Custom SQL ต้อง Admin (2026-10-29)
โค้ดปัจจุบันที่ป้องกัน
backend/internal/adapter/inbound/http/middleware/permission.go:41Allows,:62RequireRightbackend/internal/adapter/inbound/http/process/permission.go:23routeRights,:57RequiredRight(ไม่พบใน map = admin ที่:129-133),:138QueryRequiredRight,:184sqlBatchRightbackend/internal/adapter/outbound/identity/postgres_repository.go:69-109MenuRightsกรองdatabase_namebackend/internal/application/process/perm_wh_shelf.go:26,42,118;report.go:121,378;report_menu_ic.go:54-60frontend/account/tabs/TabsContext.tsx:27,66;frontend/src/config/smlMenu.ts:277,354- ช่องว่างจากการอ่านโค้ด (ไม่ใช่ประวัติ): batch ผสมจัดชั้นตาม verb แรก (
verbs[0]) และMenuRightsฝั่ง backend เป็น OR ทุกเมนู ไม่ใช่รายจอ
บทเรียน / กฎที่ได้
- การ์ดสิทธิ์ต้อง fail-closed: route ใหม่ที่ไม่ลงทะเบียน = Admin
- สิทธิ์ Add/Edit อยู่ใน body (
isNew) ต้องpeekJSONไม่ใช่ดูแค่ path - ทุกประตูเขียน (process, query, blob) ใช้การ์ดเดียวกัน ปุ่มบนจอไม่ใช่ความปลอดภัย
- ตารางสิทธิ์ต้องมี
database_nameและเทสต์ทั้งกรณีฐานตรงและค่าว่าง - ฟีเจอร์ที่ข้ามกฎรายผู้ใช้ (Custom SQL) ต้อง Admin หรือถูกปฏิเสธเมื่อรายงานถูกจำกัดสิทธิ์
ดูเพิ่ม
การตรวจสิทธิ์เมนูของ route process (Process route rights) · สิทธิ์คลัง/ที่เก็บรายกลุ่มผู้ใช้ (perm_wh_shelf) · บทเรียนการล็อกการเขียนผ่าน query gateway (Query Gateway Write Lockdown) · บทเรียนตัวตนผู้เช่า การล็อกอิน และ session (Tenant, Auth & Sessions) · เช็กลิสต์ความปลอดภัย API: ตัวตน สิทธิ์ และช่องโหว่เว็บ (Secure API Checklist) · history-overview
ที่มาในโค้ด
- git:2c273e19, git:5f188fc3, git:0d77e6fb, git:a264a99a, git:6cb904f7, git:13f953cc
- backend/internal/adapter/inbound/http/process/permission.go:23, :57, :138