API Key สำหรับระบบภายนอก
ภาพรวม
API Key ใช้ให้ระบบภายนอกของลูกค้า เช่น POS, CRM หรือเว็บไซต์ของลูกค้าเอง สามารถเรียกเข้ามาที่ client-api ได้โดยไม่ต้องใช้ JWT ของผู้ใช้ CMS โมดูลนี้คือหน้าจัดการ key ครอบคลุมการสร้าง แก้ไขชื่อ เปิดหรือปิดสถานะ และลบ
route ทั้งหมดอยู่บน group public ร่วมกับ JwtLoginAuth และ ModuleGate("api-key")
กล่าวคือผู้เรียกยังต้องมี token ที่ล็อกอินแล้ว แต่ไม่บังคับว่าต้องเลือก LINE OA ก่อน
คำเตือนสำคัญ: โมดูลนี้ถูก port มาแบบหนึ่งต่อหนึ่ง พร้อมกับ bug ของโค้ด TypeScript หลายจุด ซึ่งมีคอมเมนต์กำกับไว้ในโค้ดว่าไม่ให้แก้ ผู้ที่จะเข้ามา debug ควรทราบพฤติกรรมเหล่านี้ก่อน
Business Flow
GET /api/api-keyแสดงรายการ key ของ OA ปัจจุบัน แบบแบ่งหน้าในรูปแบบ{data, total}POST /api/api-keyสร้าง key ใหม่GET /api/api-key/:idดูรายละเอียดของ keyPUT /api/api-key/:idแก้ไขข้อมูล และPUT /api/api-key/:id/statusเปิดหรือปิดการใช้งานDELETE /api/api-key/:idลบ key- ระบบภายนอกนำค่า key ไปแนบใน request ที่ยิงไปยัง client-api
ซึ่ง client-api จะตรวจสอบกับตาราง
api_key
พฤติกรรมและ bug ที่คงไว้ตามโค้ดเดิม
รายละเอียดเหล่านี้ระบุไว้ใน service.go
POSTที่ไม่ส่งฟิลด์keyมาใน body จะทำให้ INSERT ขาดคอลัมน์keyซึ่งเป็น NOT NULL เกิด Postgres error และตอบ 500 พร้อมAPP_000— สร้างสำเร็จได้เฉพาะกรณีที่ client ส่งkeyมาเองfindAllค้นหาด้วยคอลัมน์api_key.nameและapi_key.keywordsซึ่ง ไม่มีอยู่จริงในตาราง (ถูก copy มาจากโมดูล auto-response) ดังนั้นการส่ง?search=ที่ไม่ว่าง หรือ?orderBy=nameจะทำให้เกิด 500- หากไม่ส่ง
?lineOaIdมา SQL จะกลายเป็นline_oa_id = NULLและคืนผลลัพธ์เป็น{"data":[],"total":0} - การส่ง
?status=หลายค่าจะทำให้เกิดการเทียบ array literal กับคอลัมน์ enum และตอบ 500 update()ตรวจสอบชื่อซ้ำแล้วไม่ได้ใช้ผลลัพธ์ (คงไว้เพื่อ parity) และหาก body มี property ที่ไม่ตรงกับคอลัมน์ใดจะตอบ 500updateStatus()ไม่ ล้าง cache ของ find-all
ไฟล์และฟังก์ชันหลัก
โค้ดอยู่ที่ internal/modules/apikey/ ประกอบด้วย controller.go, service.go และ dto.go
| Method | Route | Handler | Guard |
|---|---|---|---|
| GET | /api/api-key | ct.findAll | JwtLogin + ModuleGate |
| GET | /api/api-key/:id | ct.findById | JwtLogin + ModuleGate |
| POST | /api/api-key | ct.create | JwtLogin + ModuleGate |
| PUT | /api/api-key/:id | ct.update | JwtLogin + ModuleGate |
| PUT | /api/api-key/:id/status | ct.updateStatus | JwtLogin + ModuleGate |
| DELETE | /api/api-key/:id | ct.deleteById | JwtLogin + ModuleGate |
ลำดับ middleware คือ jwtLogin แล้วตามด้วย gate ก่อนถึง handler
เหตุผลคือ guard ต้องรันก่อนเพื่อเติมค่า selfId และ organizationId ลงใน CLS
ให้ gate นำไป resolve ได้ หากค่าเหล่านี้ไม่ถูกเติม gate จะ fail open
จุดเชื่อมต่อกับ Service อื่น
- Permission — ต้องผ่าน
JwtLoginAuthและModuleGate(d, "api-key")ลูกค้าที่ organization ปิดโมดูลapi-keyไว้จะได้ 403 ส่วนผู้ใช้ประเภท onemoby จะ bypass ทั้งนี้PolicyModuleApiKeyมีอยู่ใน enum แต่ไม่ได้ถูกนำมา annotate route ชุดนี้ - ตาราง —
api_key - Redis — cache ผลลัพธ์ของ find-all (มี bug ที่
updateStatusไม่ invalidate cache) - ผู้บริโภค key — line-management-client-api-go ซึ่งเป็นคนละ service
- โมดูลข้างเคียงที่ไม่มี route — ทะเบียน API Client