ทำไมเขียนข้อมูลผ่าน /query/exec ไม่ได้
ตอบสั้น: เพราะ ADR-0011 ล็อกไว้โดยตั้งใจ — ตารางเงิน/สต็อก/GL ห้ามเขียนด้วย SQL จากเบราว์เซอร์ (ถูกปฏิเสธแม้เป็น Admin level 9) ต้องเรียก /api/process ที่ทำกฎบัญชีใน transaction เดียว ส่วนตารางอื่น ผู้ใช้ level ต่ำกว่า 9 เขียนได้เฉพาะตารางใน allow-list legacyClientWritable
รายละเอียด
ลำดับการตรวจตอน POST /query/exec หรือ /query/execBatch (ดูภาพรวมที่ Query Gateway (/query/list, /query/limit, /query/batch, /query/exec) ทำงานอย่างไร):
RequireRightตรวจสิทธิ์เมนู Add/Edit/Delete ตามคำกริยา SQL ตัวแรก (insert=เพิ่ม,update=แก้,delete=ลบ) —permission.go:138ไม่มีสิทธิ์ = 403NewWriteStatementต้องเป็นINSERT/UPDATE/DELETE(หรือWITHที่มี DML) และห้าม DDL/MERGE(ErrNotWriteOnly, 400)ValidateUserLevel: level < 9 แก้sml_user_list,sml_database_list*,erp_optionไม่ได้ValidateClientPolicy(write_policy.go:77) เฉพาะคำขอจากเบราว์เซอร์:
| เงื่อนไข | ผล |
|---|---|
ตารางเงิน/สต็อก/GL (ic_trans*, ap_ar_trans*, as_trans*, cb_trans*, cb_chq_list, gl_journal*, gl_trans*, gl_summary_* ฯลฯ ยกเว้น gl_journal_book) |
ErrMoneyTableViaExec 403 ทุกระดับ |
ic_inventory แต่ SQL แตะ balance_qty, average_cost, accrued_in_qty ฯลฯ |
ErrMoneyTableViaExec |
| หาตารางเป้าหมายไม่เจอ | ErrAdminOnlyWrite |
level < 9 และตารางไม่อยู่ใน legacyClientWritable |
ErrAdminOnlyWrite |
| level >= 9 และเป็นตารางอื่น | ผ่าน |
โค้ดภายใน Go (module อย่าง crm, procure, wms) เรียก use case เดียวกันด้วย ClientRequest=false จึงไม่ถูกนโยบายนี้ ตารางเงินยังถูกแก้ผ่าน handler ของ /process ได้ตามปกติ
วิธีแก้เมื่อเจอ error: อย่าพยายามเลี่ยง ให้ใช้ action ใน /api/process ที่ตรงงาน (บันทึกเอกสาร, ยอดยกมา, ตรวจราคา ฯลฯ — Process engine (/process) เรียก action อย่างไร และเพิ่ม action ใหม่ต้องแก้ที่ไหนบ้าง) ถ้าเป็นตารางมาสเตอร์ใหม่ที่ผู้ใช้ level ต่ำต้องแก้ ต้องเพิ่มชื่อใน legacyClientWritable หรือทำ endpoint ใน Go (เพิ่มจอข้อมูลหลัก (master) ใหม่ต้องแก้ที่ไหนบ้าง และทำไมผู้ใช้ทั่วไปบันทึกไม่ได้)
ข้อควรระวัง
/blob/insertใช้กติกาเดียวกันผ่านValidateClientInsert(write_policy.go:64)- ตัวอย่างในหน้าจอ:
StandardMasterScreen.tsxมี comment ว่าเอกสารแต้ม 801/802 (ic_trans) ถูก/query/execปฏิเสธ ต้องผ่าน/api/process
ดูเพิ่ม
- นโยบายล็อกการเขียนผ่าน Query Gateway (Query write policy / lockdown)
- ADR-0011 ล็อก SQL เขียนจาก browser: ตารางเงิน/สต๊อก/GL ผ่าน /api/process เท่านั้น
- ADR-0006 /query/exec รับเฉพาะ DML + ตารางระบบต้อง level>=9 (ถูกแทนด้วย ADR-0011)
- บทเรียนการล็อกการเขียนผ่าน query gateway (Query Gateway Write Lockdown)
- ทำไมเข้าเมนู/กดบันทึกแล้วขึ้น 403 ไม่มีสิทธิ์ และตั้งสิทธิ์เมนูให้ผู้ใช้อย่างไร
- แทรกแถวพร้อมรูปภาพ: POST /blob/insert + MinIO (Blob insert)
ที่มาในโค้ด
backend/internal/domain/query/write_policy.go:16ข้อความErrMoneyTableViaExec/ErrAdminOnlyWritebackend/internal/domain/query/write_policy.go:77ValidateClientPolicybackend/internal/application/query/service.go:105เรียกValidateClientPolicyเมื่อClientRequest(execBatch บรรทัด 146)backend/internal/adapter/inbound/http/query/handler.go:245ClientRequest: true(execBatch บรรทัด 299)backend/internal/adapter/inbound/http/process/permission.go:138QueryRequiredRightmap คำกริยา SQL → สิทธิ์เมนู