หน้าจอผู้ดูแลระบบส่วนกลาง (Admin Console)
โซน /admin/* สำหรับผู้ดูแลระบบ (session mode === "admin") ใช้จัดการ Provider, ฐานข้อมูล, ผู้ใช้, กลุ่ม, สิทธิ์เมนู และ MCP Token แยกจากแอปบัญชีหลัก ((app))
ทุกหน้าเป็นหน้าบางๆ ที่ส่ง currentProvider ให้ component ใน account/admin/screens/ แล้วเรียก /api/admin/* (proxy ไป backend /api/v1/admin/*).
ทำงานอย่างไร
1) ประตูเข้า (layout)
(admin)/layout.tsx:18-21: ไม่มี session →/login; ไม่ใช่mode==="admin"และไม่ใช่ผู้ชมสาธิต (isDemoCentralViewer) →/home.- ผ่านแล้วห่อด้วย
AdminShell(shared/layout/AdminShell.tsx) โดยreadOnly={demoViewer}; โหมดอ่านอย่างเดียวขึ้นแถบเหลืองadmin-demo-readonly-banner(AdminShell.tsx:80-87). ปุ่มออกจากระบบเรียกPOST /api/auth/logoutแล้วrouter.replace("/login")(AdminShell.tsx:31-35). - หน้าแรก
/admin((admin)/admin/page.tsx) วาดการ์ดเมนูจากadminMenuGroups+ ปุ่มMockResetButton(POST /api/admin/reset, ใช้ได้เฉพาะโหมดข้อมูลจำลองreset/route.ts:11-12).
2) เมนู 3 กลุ่ม (src/config/adminMenu.ts, adminMenuGroups เริ่มบรรทัด 39) ทุกรายการ status:"ready" (ค่า "todo" มีในชนิดข้อมูล บรรทัด 31)
| กลุ่ม | เมนู (ไทย) | หน้า /admin/... |
Component |
|---|---|---|---|
| User Manage (Provider) | กำหนดผู้ใช้และกลุ่มผู้ใช้ | users |
UsersScreen → UsersTab |
| จัดกลุ่มผู้ใช้ | user-groups |
UserGroupsScreen |
|
| เปลี่ยนข้อความในระบบ | system-text |
SystemTextScreen |
|
| เปลี่ยนรหัสผ่าน | change-password |
ChangePasswordScreen |
|
| กำหนดสิทธิ์กลุ่มใช้งาน | group-permission |
GroupPermissionScreen |
|
| กำหนดผู้มีสิทธิ์เข้าใช้ข้อมูล | data-access |
DataAccessScreen |
|
| Database Manage (Provider) | กำหนดกลุ่มข้อมูล | data-groups |
DataGroupsScreen |
| สร้างฐานข้อมูลใหม่ | create-database |
CreateDatabaseScreen |
|
| เชื่อมฐานข้อมูล | databases |
DatabasesScreen → DatabasesTab |
|
| กำหนดการเข้าถึงข้อมูล | data-permission |
DataPermissionScreen |
|
| ตรวจสอบฐานข้อมูล | check-database |
CheckDatabaseScreen |
|
| Database Information | database-info |
DatabaseInfoScreen |
|
| โอนข้อมูล | transfer |
TransferDataScreen |
|
| ระบบและการเชื่อมต่อ AI ภายนอก (เฉพาะเว็บ) | จัดการ Provider | providers |
ProvidersScreen → ProvidersTab |
| จัดการ MCP Token (AI Read-Only) | mcp-tokens |
McpTokenScreen |
ไฟล์ component อยู่ใน account/admin/screens/ (alias @/components/admin/screens/X); ExtraAdminScreens.tsx รวม 7 จอ: user-groups (33), system-text (256), group-permission (379), data-permission (391), create-database (620), check-database (700), transfer (815).
3) โครงร่วมของจอ
AdminScreenFrame(AdminScreenFrame.tsx:13) = หัวเรื่อง + note + ลิงก์กลับ/admin.ProviderScopedScreen(ProviderScopedScreen.tsx:17) ใช้useProviders(currentProvider)+ProviderPickerให้เลือก Provider แล้วส่งค่าให้ลูกเป็น(provider) => .... จอ users/databases/data-access/ฯลฯ จึงสลับ Provider ได้โดยไม่ผูกกับ session.
4) จอที่เรียก /api/admin/* ตรงๆ (CRUD)
| จอ | Endpoint ที่เรียก |
|---|---|
UsersTab |
GET /api/admin/users + /databases; บันทึก POST/PATCH /api/admin/users; ลบ DELETE ...users?provider=&user= (UsersTab.tsx:52-53,75-76,95-96) |
DatabasesTab |
GET/POST/PATCH /api/admin/databases; ลบ DELETE ...databases?provider=&database= (DatabasesTab.tsx:39,57-58,77-78) |
ProvidersTab |
POST/PATCH /api/admin/providers; ลบ DELETE ...providers?code= (ProvidersTab.tsx:53-54,73-74) |
DataAccessScreen (note "ผูกผู้ใช้กับฐานข้อมูลที่เข้าได้") |
GET users+databases, PATCH /api/admin/users (DataAccessScreen.tsx:26-27,74) |
DataGroupsScreen (note "กลุ่มข้อมูล ที่ผู้ใช้ต้องกรอกตอน login") |
GET databases, PATCH /api/admin/databases เปลี่ยนชื่อกลุ่ม (DataGroupsScreen.tsx:23-24,58) |
DatabaseInfoScreen |
GET /api/admin/database-info?provider= (DatabaseInfoScreen.tsx:16-17) |
CreateDatabaseScreen |
POST /api/admin/databases (ExtraAdminScreens.tsx:648) |
ChangePasswordScreen โหมดผู้ดูแล |
PATCH /api/admin/users ส่ง user_password (รหัสยาว >= 4 ตัว ChangePasswordScreen.tsx:60,66) |
5) จอที่ยิง SQL ผ่าน main-query (SQL สร้างในเบราว์เซอร์)
UserGroupsInner(ExtraAdminScreens.tsx:45): อ่าน/เขียนตารางsml_group_listและsml_user_and_groupด้วยPOST /api/admin/main-query(บรรทัด 60,65,92,112,119,124) โดย escape เครื่องหมาย'ด้วยฟังก์ชันesc()(บรรทัด 26-28).CheckDatabaseInner(บรรทัด 712-735): นับคอลัมน์ต่อตารางจากinformation_schema.columns(schemapublic) และส่งdatabase: targetDbไปด้วย แต่ route ปฏิเสธถ้าdatabaseต่างจากsession.databaseและไม่ส่งdatabaseต่อให้ backend (main-query/route.ts:29-40) — พฤติกรรมตอนเลือกฐานอื่นยังไม่ยืนยัน.- ตัว route (
main-query/route.ts:10-45): ต้องผ่านrequireSystemAdmin; ถ้า bodyproviderไม่ตรง session → ปฏิเสธ "ไม่อนุญาตให้รันคำสั่งข้าม Provider ของเซสชันปัจจุบัน" (บรรทัด 24-26); ถ้าdatabaseไม่ตรง session → ปฏิเสธ (บรรทัด 29-31); ส่งต่อไป backend เฉพาะprovider(จาก session),sql,mode("query"เป็นค่าเริ่มต้น หรือ"exec").
6) เมทริกซ์สิทธิ์เมนู (PermissionMatrixInner, ExtraAdminScreens.tsx:416)
mode="group"=GroupPermissionScreen(เลือกกลุ่มจากmain-query);mode="user"=DataPermissionScreen(เลือกผู้ใช้จากGET /api/admin/users) (บรรทัด 429,440).- โหลดสิทธิ์
GET /api/admin/menu-permissions?kind=<group|user>&code=<เป้าหมาย>(บรรทัด 456) และบันทึกPUT /api/admin/menu-permissions(บรรทัด 485) — สิทธิ์ต่อเมนูเป็น อ่าน/เพิ่ม/แก้ไข/ลบ (ตาม note ของจอ). SystemTextScreenใช้ endpoint เดียวกันด้วยkind=tooltip&code=ALL(GET บรรทัด 279, PUT บรรทัด 293) เพื่อแก้ข้อความ tooltip ของระบบ.
7) จอพิเศษ
ChangePasswordScreen(ChangePasswordScreen.tsx:412-430): ถ้าส่งmenuCodeมา =SelfChangePasswordScreen(ผู้ใช้เปลี่ยนรหัสตัวเอง ใช้GET+POST /api/auth/change-passwordที่บรรทัด 182,224; ผู้ใช้ Google ไม่แสดงฟอร์ม บรรทัด 196; โหมดสาธิตห้ามเปลี่ยน บรรทัด 201-202; รหัสใหม่ต้องไม่ซ้ำรหัสเดิม บรรทัด 217). ถ้าไม่ส่ง = โหมดผู้ดูแลตั้งรหัสให้ผู้ใช้ใน Provider. จอตัวเองถูกลงทะเบียนในแอปบัญชีที่menu_change_password(account/tabs/screenRegistry.tsx:430) และmenu_saletools_change_password(บรรทัด 438).McpTokenScreen(McpTokenScreen.tsx:91, 1,190 บรรทัด): ดึงรายการGET /api/mcp/tokens(บรรทัด 141), สร้าง token แบบmode:"readonly"ระบุdatabaseCodes+days(บรรทัด 238-244), เพิกถอนด้วยPOSTaction:"revoke"(บรรทัด 270-273), สถานะactive|expired|revokedคำนวณจากrevokedAt/expiresAt(บรรทัด 71-73), ทดสอบเรียกเครื่องมือผ่าน JSON-RPCtools/callที่/api/mcpด้วย Bearer token (บรรทัด 370-380). ถูกลงทะเบียนในแอปบัญชีที่menu_mcp_tokensรหัส 1.1.21 (screenRegistry.tsx:273-281). (route/api/mcp/*อยู่นอกขอบเขตที่อ่าน)TransferDataScreen(ExtraAdminScreens.tsx:827-899): เลือกฐานต้นทาง/ปลายทางจากGET databasesและติ๊กชุดข้อมูล 7 รายการ (ic_inventory,ic_unit,ic_warehouse,ar_customer,ap_supplier,gl_chart_of_account,erp_doc_format; บรรทัด 837-845) แต่ปุ่ม "เริ่มโอนข้อมูล" แค่setDone(...)แสดงข้อความ "เรียบร้อย" (บรรทัด 892) ไม่มีการเรียก API โอนข้อมูลจริงในจอนี้ และ checkbox เป็นdefaultCheckedไม่ถูกอ่านค่า.
/api/admin routes
| Route | Method | ปลายทาง backend | สิทธิ์ |
|---|---|---|---|
database-info |
GET | /api/v1/admin/database-info?provider= |
requireSystemAdminView + demoSafe (route.ts:31-40) |
databases |
GET/POST/PATCH/DELETE | /api/v1/admin/databases |
GET = View; เขียน = requireSystemAdmin (route.ts:33,51) |
providers |
GET/POST/PATCH/DELETE | /api/v1/admin/providers |
เช่นเดียวกัน (route.ts:27,40) |
users |
GET/POST/PATCH/DELETE | /api/v1/admin/users |
เช่นเดียวกัน; AdminUserView = Omit<SmlUser,"user_password"> (route.ts:20) |
menu-permissions |
GET/PUT | /api/v1/admin/menu-permissions |
GET = View + demoSafe (route.ts:14-26), PUT = requireSystemAdmin (route.ts:29-34) |
main-query |
POST | /api/v1/admin/main-query |
requireSystemAdmin + บังคับ Provider/Database ตาม session |
reset |
POST | (ไม่มี — เฉพาะ mock) | requireSystemAdmin; ไม่ใช่ mock → 400 |
เส้นทาง databases/providers/users/database-info มีสาขา mock เมื่อ USE_MOCK (อ่านจาก readDb()), โหมดจริงส่งต่อด้วย proxyToService.
ที่มาในโค้ด
frontend/src/app/(admin)/layout.tsx:18-26— ด่านสิทธิ์mode==="admin"/ ผู้ชมสาธิต และAdminShell readOnly.frontend/src/config/adminMenu.ts:26-39,162— ชนิดเมนู,adminMenuGroups,findAdminMenu.frontend/shared/layout/AdminShell.tsx:31-35,80-87— logout และแถบโหมดอ่านอย่างเดียว.frontend/account/admin/ProviderScopedScreen.tsx:17-32,AdminScreenFrame.tsx:13— โครงร่วมของจอ.frontend/account/admin/UsersTab.tsx,DatabasesTab.tsx,ProvidersTab.tsx— CRUD (cite ในตาราง).frontend/account/admin/screens/ExtraAdminScreens.tsx:33,256,379,391,416,620,700,815— จอที่ยิงmain-query/menu-permissions.frontend/account/admin/screens/ChangePasswordScreen.tsx:162,412-430และMcpTokenScreen.tsx:91,141,238,270,370— จอพิเศษ.frontend/src/app/api/admin/*/route.ts— proxy ฝั่ง server (cite ในตาราง route).
ดูเพิ่ม
เส้นทาง API ฝั่ง Next.js ที่ส่งต่อไป Go backend (API proxy routes) · เซสชันและการยืนยันตัวตนฝั่ง frontend (Auth session & tokens) · โครงหน้าเว็บและการนำทาง (App shell & routing) · หน้าเข้าสู่ระบบและเลือกฐานข้อมูล (Login & select database) · ทะเบียนหน้าจอและโครงเมนู (Screen registry & smlMenu) · ตัวเรียก API และตัวประกอบ SQL ฝั่งเบราว์เซอร์ (api-client, query-client, sml-query-builder) · ภาพรวม Frontend ของ SML Ai Account (Frontend overview) · ภาพรวม Backend Go ของ SML Ai Account (Backend overview)