Files
alla-tms/docs/role-permission-review.md
2026-07-16 09:53:14 +07:00

15 KiB

Role Permission Review

วันที่ตรวจสอบ: 2026-06-30

Scope

เอกสารนี้เป็นการตรวจสอบระบบสิทธิ์การเข้าถึงของ 3 กลุ่มหลัก:

  • Employee
  • HRD Admin
  • IT Admin

ขอบเขตที่ตรวจ:

  • การมองเห็นเมนูใน sidebar
  • การกัน direct URL ที่ระดับ page
  • การกันสิทธิ์ที่ระดับ API / server-side
  • การจำกัดขอบเขตข้อมูล
  • ความสอดคล้องระหว่าง requirement กับ implementation ปัจจุบัน

ไฟล์หลักที่ใช้ตรวจ:

  • src/config/nav-config.ts
  • src/hooks/use-nav.ts
  • src/lib/auth/roles.ts
  • src/lib/auth/session.ts
  • src/lib/auth/page-guards.ts
  • src/proxy.ts
  • src/app/dashboard/**
  • src/app/api/**

Requirement Summary

จากแผนงานที่ให้ตรวจ ระบบนี้ควรแยกสิทธิ์อย่างน้อยเป็น 3 ระดับ:

  • Employee เห็นเฉพาะส่วนที่ใช้กับตัวเอง และข้อมูลต้องถูก scope เป็นของตัวเอง
  • HRD Admin จัดการข้อมูลฝั่งงานอบรมและข้อมูลบุคลากรในองค์กรได้
  • IT Admin จัดการสิทธิ์ระดับสูงกว่า HRD และเข้าถึงส่วน technical / audit ได้

ประเด็นสำคัญที่แผนเน้นเป็นพิเศษ:

  • เมนูและหน้าจอต้องสอดคล้องกับสิทธิ์จริง
  • ห้ามพึ่งแค่ซ่อนเมนู ต้องกันที่ server ด้วย
  • ข้อมูลของ Employee ต้องไม่ทะลุไปเห็นของคนอื่น
  • ฟังก์ชัน Import พนักงาน ควรถูกทบทวน/ถอดออกจาก flow ถ้าไม่ได้ต้องการใช้งานแล้ว

Findings

1. High: หน้าและ API Import พนักงาน ยังเปิดใช้งานอยู่

สถานะ: Fail

หลักฐาน:

ผลกระทบ:

  • ถ้า requirement ล่าสุดต้องการยกเลิก flow นี้ ปัจจุบันถือว่ายังไม่ปิดจริง
  • ผู้ใช้ HRD / IT ยังเข้าใช้งานได้ผ่านปุ่ม, direct URL และ API

คำแนะนำ:

  • ถ้าต้องการถอดฟังก์ชันนี้จริง ควรลบปุ่ม, ปิดหน้า route, ปิด API และตรวจ flow ที่เกี่ยวข้องกับ master-review ต่อด้วย

2. Medium: สิทธิ์ฝั่ง Employee สำหรับเมนูบางหน้าไม่สอดคล้องกับสิทธิ์จริงของหน้า

สถานะ: Need Review

หลักฐาน:

ข้อสังเกตเพิ่ม:

  • หน้า Announcements ใช้ requireEmployeeDashboardAccess() ใน src/app/dashboard/announcements/page.tsx
  • หน้า Notifications ใช้ requireEmployeeDashboardAccess() ใน src/app/dashboard/notifications/page.tsx
  • แต่ใน nav-config.ts เมนู Announcements ถูกวางไว้ในกลุ่ม HRD/IT เท่านั้น และ Notifications ไม่มีใน sidebar

ผลกระทบ:

  • สิทธิ์จริงของระบบกับสิ่งที่ผู้ใช้เห็นในเมนูไม่ตรงกัน
  • ผู้ใช้ employee อาจ “เข้าได้แต่ไม่เห็นเมนู”

คำแนะนำ:

  • ตกลงให้ชัดว่าหน้าใดควรเป็น employee-facing
  • จากนั้น sync ระหว่าง nav-config.ts กับ page/API permission ให้ตรงกัน

3. Medium: โมเดลสิทธิ์ IT กับ HRD ยังพึ่งการตีความทางอ้อมมากกว่าตารางสิทธิ์ที่ชัด

สถานะ: Need Review

หลักฐาน:

ผลกระทบ:

  • ตอนนี้ระบบทำงานแบบ “IT เข้าส่วน HRD ได้ทั้งหมด” ซึ่งอาจถูกต้องก็ได้
  • แต่ถ้าอนาคตอยากแยกสิทธิ์ HRD กับ IT ให้ต่างกันมากขึ้น จะตามแก้ยาก เพราะ logic ผูกกันอยู่หลายชั้น

คำแนะนำ:

  • ถ้าต้องการให้ IT = สิทธิ์มากกว่า HRD แบบตั้งใจ ถือว่าใช้งานได้
  • แต่ถ้าต้องการ matrix สิทธิ์ที่ตรวจสอบง่าย ควรมี role-permission matrix กลางที่อ่านแล้วตอบได้ทันทีว่าแต่ละ role ทำอะไรได้บ้าง

4. Low: เอกสาร RBAC ปัจจุบันไม่ตรงกับ implementation บางจุด

สถานะ: Need Review

หลักฐาน:

ผลกระทบ:

  • คนดูเอกสารอาจเข้าใจสิทธิ์ผิด
  • เสี่ยงตัดสินใจต่อยอด feature จากเอกสารที่ไม่ตรงโค้ดจริง

คำแนะนำ:

  • อัปเดตเอกสารให้ตรงกับ implementation ปัจจุบัน

Menu Visibility Review

Employee

ผลที่พบ:

  • เห็น Overview, Training Records, Online Lessons
  • ไม่เห็น Reports จาก sidebar แม้ว่าหน้า reports จะเข้าได้จริง
  • ไม่เห็น Announcements และ Notifications จาก sidebar แม้ว่าหน้าเหล่านี้เปิดสิทธิ์ employee

สรุป: Partial

HRD Admin

ผลที่พบ:

  • เห็น Pending Review
  • เห็นกลุ่ม ข้อมูลหลัก และเข้าถึง Employee Directory, Courses, Training Policy, Announcements
  • เข้า Import Employees ได้ผ่าน direct URL และจากปุ่มในหน้า employee directory
  • ไม่เห็น Users เพราะเมนูนั้นเปิดเฉพาะ IT

สรุป: Mostly Pass

IT Admin

ผลที่พบ:

  • เห็นเมนู Users
  • เห็นส่วนของ HRD ได้ทั้งหมดผ่าน role mapping
  • เห็น Audit Logs เฉพาะ super_admin

สรุป: Pass

Route Protection Review

ผ่าน

  • หน้า employee-facing ใช้ requireEmployeeDashboardAccess()
  • หน้า HRD ใช้ requireHRDDashboardAccess()
  • หน้า IT ใช้ requireITDashboardAccess() หรือ requireUserManagementDashboardAccess()

หลักฐานสำคัญ:

ข้อสังเกต

  • src/proxy.ts กันได้แค่ “ล็อกอินหรือยัง”
  • การกัน “สิทธิ์ role ไหนเข้าได้” ยังต้องพึ่ง page guard และ API handler ต่อ ซึ่งตอนนี้ถือว่าทำถูกทิศทางแล้ว

สรุป: Pass

API / Server Action Permission Review

ผ่าน

ผ่านแบบมีเงื่อนไข

  • Training Records ใช้ requireOrganizationAccess() แล้วคุมต่อด้วย scope และ review permission ภายใน service
  • Reports Export กัน employee ไม่ให้ export รายงานรวม โดยอนุญาตเฉพาะ employeeTranscript

สรุป: Pass

Data Scope Review

Employee

ผ่าน:

HRD / IT

ผ่าน:

สรุป: Pass

Hardcoded Roles Review

สิ่งที่พบ:

  • role string หลักกระจุกอยู่ใน src/lib/auth/roles.ts
  • แต่ยังมีการอ้าง role ตรง ๆ ซ้ำใน nav-config.ts, session.ts, เอกสาร, และบาง feature

ประเมิน:

  • ยังไม่ถึงขั้นกระจายมั่ว
  • แต่ยังไม่มี permission matrix กลางที่เป็น single source of truth

สรุป: Acceptable but should improve later

Summary

ภาพรวมปัจจุบัน:

  • ระบบกันสิทธิ์ที่ระดับ page และ API ถือว่าใช้ได้
  • data scope ของ employee ฝั่ง training records และ reports ถือว่าปลอดภัยในระดับหนึ่ง
  • จุดที่ไม่ตรง requirement ชัดที่สุดคือ Import พนักงาน ยังไม่ถูกถอดออกจริง
  • อีกจุดที่ควรรีบจัดระเบียบคือความไม่ตรงกันระหว่าง “เมนูที่เห็น” กับ “สิทธิ์จริงของหน้า” โดยเฉพาะ Reports, Announcements, Notifications
  1. ตัดสินใจให้ชัดว่า Import พนักงาน จะเก็บหรือจะถอด แล้วปิดทั้ง UI, route, API ให้ครบ
  2. ทำ matrix สิทธิ์ของ Employee / HRD / IT แบบสั้น ๆ แล้วใช้เป็นตัวเทียบกับ nav-config.ts
  3. sync nav-config.ts กับ page/API permission ให้ผู้ใช้เห็นเมนูตรงกับสิทธิ์จริง
  4. อัปเดต docs/nav-rbac.md ให้ตรงกับโค้ดปัจจุบัน