API /admin/providers และ AdminAuth
ลงทะเบียน provider (ผู้ให้บริการ = tenant, ผู้เช่าแต่ละรายมีฐาน Main ของตัวเอง ดู ทะเบียน Provider แบบไฟล์ JSON (Provider registry), โมเดลผู้เช่าหลายราย: Tenant, Provider, Main DB, Company (Multi-tenant model), ADR-0003 ข้อมูลผู้ใช้และสิทธิ์อยู่ใน DB ของแต่ละผู้เช่า ไม่ใช่ control-plane) เข้าระบบ. กลุ่มนี้ ไม่ใช้ JWT แต่ใช้กุญแจผู้ดูแลแบบคงที่ใน header เดียว. กลุ่ม REST ผู้ดูแลอีกชุดที่ใช้กุญแจเดียวกันคือ API คอนโซลผู้ดูแล /api/v1/admin — provider, user, database, main-query, menu-permissions (Admin console API) และ API Workspace — ล็อกอิน Google, เลือกฐานบริษัท, สมาชิก, สิทธิ์จอ, ผูก LINE (Admin workspace API).
AdminAuth (middleware/adminauth.go:18-28)
- Header:
X-Admin-Api-Key: <adminKey>(ค่าจาก env ของ server ไม่ใส่ลงโน้ต) - เทียบแบบ constant-time (
subtle.ConstantTimeCompare); ถ้ากุญแจฝั่ง server ว่าง จะปฏิเสธทุกคำขอเสมอ (ไม่มีทางปล่อยเปิดโดยลืมตั้งค่า) - ไม่ผ่าน = 401
{"error":{"message":"missing or invalid admin API key"}} - ใช้กับ:
/admin/*(router.go:114),/api/v1/admin/*(router.go:213),/api/v1/mcp/tokens(api-mcp)
POST /admin/providers (tenant/handler.go:66)
ทดสอบการเชื่อมต่อฐานข้อมูลจริงก่อน แล้วลงทะเบียนเมื่อทดสอบผ่านเท่านั้น (ล้มเหลว = ไม่บันทึกอะไร).
- Request:
POST /admin/providers (X-Admin-Api-Key: <adminKey>)
{"code":"<providerCode>","name":"<ชื่อผู้ให้บริการ>",
"connection":{"host":"<host>","port":5432,"database":"<dbName>","user":"<dbUser>","password":"<dbPassword>","sslmode":"disable"}}
- Response 201:
{"code","name","status":"active","createdAt":"<RFC3339>"}(ไม่คืนรายละเอียดการเชื่อมต่อ/รหัสผ่าน) - Errors: 400 body ผิด/ข้อมูลไม่ครบ/เชื่อมฐานไม่ได้, 401 กุญแจผิด, 409 รหัส provider ซ้ำ
- การจัดเก็บ config ของ provider ดู ADR-0001 เก็บ config ของผู้เช่า (Provider) เป็นไฟล์ JSON ไม่ใช่ตาราง DB และ ADR-0002 รหัสผ่าน DB ของผู้เช่าเก็บเป็น base64 ไม่ได้เข้ารหัส
GET /admin/providers (tenant/handler.go:104)
- Response 200: อาร์เรย์
[{"code","name","status","createdAt"}]เฉพาะฟิลด์ดัชนี ไม่มีรายละเอียดการเชื่อมต่อหรือรหัสผ่าน - Errors: 401
ขีดจำกัด
ไม่มี MaxBytesReader ในตัว handler (ขีดรวมคือ timeout 60 วินาทีของ router, router.go:64); ไม่พบ rate-limit.
ผู้เรียกฝั่งหน้าเว็บ
Next ไม่มี route ที่ส่งตรงไป /admin/providers ของ Go: หน้าจอผู้ดูแลเรียก GET|POST|PATCH|DELETE /api/admin/providers (Next) ซึ่ง proxy ไป /api/v1/admin/providers (ชุด admin console, src/app/api/admin/providers/route.ts:27,40,76,108) แทน — ดู API คอนโซลผู้ดูแล /api/v1/admin — provider, user, database, main-query, menu-permissions (Admin console API).
กุญแจแนบอัตโนมัติโดย fetchServiceWithAuthRetry เมื่อ endpoint มีคำว่า /admin (src/lib/api-server.ts:388); getAdminApiKey (api-server.ts:60) ใน production ต้องมี env ไม่งั้นตอบ 503 NO_ADMIN_API_KEY.
ที่มาในโค้ด
backend/internal/adapter/inbound/http/router.go:114-122backend/internal/adapter/inbound/http/tenant/handler.go:26-120backend/internal/adapter/inbound/http/middleware/adminauth.go:10-28backend/internal/application/tenant/service.go:28frontend/src/lib/api-server.ts:60,388;frontend/src/app/api/admin/providers/route.ts:27-108