Files
alla-tms/plans/permission-authorization.md
2026-07-16 09:53:14 +07:00

20 KiB

Prompt: Refactor Authorization เป็น Permission Template + Permission-first Model

Context

โปรเจกต์นี้คือระบบ Training Management System (TMS) ที่ปัจจุบันยังมีการตรวจสอบสิทธิ์จาก systemRole, membership.role, businessRole และ helper เช่น isHRD() / isIT()

ต้องการปรับระบบสิทธิ์ใหม่ให้เป็น Permission-first Authorization Model โดยตัดแนวคิดว่า “Role คือสิทธิ์” ออก และเปลี่ยนมาใช้ Permission Template เป็นชุดสิทธิ์ต้นแบบแทน

อ้างอิงจากแผนเดิมใน role-permission-migration-plan.md ที่ระบุว่าควรย้ายระบบจาก role/helper เดิมไปสู่ permission-based model และให้ API/server ใช้ permission เป็นตัวตัดสินสิทธิ์จริง


Final Direction

ให้เปลี่ยนแนวคิดจากเดิม:

User
  -> Role
    -> Permission

เป็น:

Organization
  -> Permission Template
    -> Permissions
      -> User Assignment
        -> User Permission Override
          -> Effective Permissions

หลักการสำคัญ:

  • Permission คือ source of truth
  • Permission Template เป็นเพียงชุดสิทธิ์ต้นแบบ
  • User ได้รับสิทธิ์จาก Template
  • User สามารถมี Permission Override รายบุคคลได้
  • ระบบต้องรองรับหลายองค์กร
  • UI ซ่อน/แสดงได้ตาม Permission
  • API/server ต้องตรวจ Permission เสมอ
  • ห้ามใช้ Role เป็นตัวตัดสินสิทธิ์หลักอีกต่อไป

Required Work

1. Audit Existing Authorization

ตรวจสอบโค้ดทั้งหมดก่อนแก้ไข

ค้นหาการใช้งาน:

systemRole
membership.role
businessRole
isHRD()
isIT()
requireHRD()
requireIT()
requireUserManagementAccess()
role === ...

ตรวจสอบในส่วน:

  • API routes
  • Server actions
  • Page guards
  • Navigation
  • Feature components
  • Data helpers
  • Auth/session helpers
  • User management
  • Middleware

ให้สรุปก่อนว่าไฟล์ใดยังใช้ role-based authorization อยู่


2. Create Permission Catalog

สร้าง permission catalog กลาง เช่น:

src/lib/auth/permissions.ts

ต้องมี permission constants และ type-safe permission list

ตัวอย่างกลุ่ม permission:

organization:manage
organization:switch

permission_template:read
permission_template:create
permission_template:update
permission_template:clone
permission_template:delete
permission_template:assign

user_permission:read
user_permission:update
user_permission:override
user_permission:remove_override

users:read
users:create
users:update
users:delete
users:manage

employee_directory:read
employee_directory:write
employee_import:run
employee_master_review:approve

training_record:self_read
training_record:self_write
training_record:read_all
training_record:write_all
training_record:submit
training_record:review
training_record:approve
training_record:reject
training_record:delete_draft
training_record:manage_attachments

announcement:read_public
announcement:read_all
announcement:create
announcement:edit_draft
announcement:delete_draft
announcement:submit
announcement:approve
announcement:reject
announcement:publish
announcement:schedule
announcement:unpublish
announcement:archive
announcement:restore
announcement:revision
announcement:preview
announcement:view_history

online_lesson:read_public
online_lesson:read_all
online_lesson:create
online_lesson:edit_draft
online_lesson:delete_draft
online_lesson:submit
online_lesson:approve
online_lesson:reject
online_lesson:publish
online_lesson:schedule
online_lesson:unpublish
online_lesson:archive
online_lesson:restore
online_lesson:revision
online_lesson:preview
online_lesson:view_history

reports:self_read
reports:organization_read
reports:export
reports:export_excel
reports:export_pdf

audit_logs:read
audit_logs:export

notifications:read
notifications:manage

3. Add Permission Template Data Model

ตรวจสอบ schema เดิมก่อนแก้ไข

ให้เพิ่มหรือปรับ database model ให้รองรับ:

organizations
permission_templates
permission_template_permissions
user_permission_template_assignments
user_permission_overrides
permission_audit_logs

โครงสร้างต้องรองรับ:

  • หลายองค์กร
  • แต่ละองค์กรมี Permission Template ของตัวเอง
  • Template สร้างได้
  • Template แก้ไขได้
  • Template Clone ได้
  • Template ลบได้
  • Template ที่ถูกใช้งานอยู่ต้องห้ามลบ หรือให้ soft delete เท่านั้น
  • User 1 คนสามารถถูก assign template ได้อย่างน้อย 1 template ต่อ organization
  • User สามารถมี permission override รายบุคคลได้
  • Override ต้องรองรับทั้ง allow และ deny
  • Override สามารถมี optional expiration date ได้ ถ้าออกแบบได้โดยไม่กระทบระบบมาก
  • ทุกการเปลี่ยนแปลงต้องมี audit log

4. Default Permission Templates

สร้าง default templates เป็น seed data ไม่ใช่ hard-code role

ต้องมี template เริ่มต้นอย่างน้อย:

Employee
HRD Staff
HRD Manager
Org Admin
IT Admin
Super Admin

ตัวอย่างสิทธิ์:

Employee

notifications:read
announcement:read_public
online_lesson:read_public
training_record:self_read
training_record:self_write
training_record:submit
reports:self_read

HRD Staff

ได้ Employee permissions และเพิ่ม:

employee_directory:read
employee_directory:write
courses:read
courses:write
training_matrix:read
training_matrix:write
training_record:read_all
training_record:write_all
announcement:read_all
announcement:create
announcement:edit_draft
announcement:delete_draft
announcement:submit
announcement:preview
online_lesson:read_all
online_lesson:create
online_lesson:edit_draft
online_lesson:delete_draft
online_lesson:submit
online_lesson:preview

ห้ามมี:

announcement:approve
announcement:publish
announcement:schedule
announcement:archive
online_lesson:approve
online_lesson:publish
online_lesson:schedule
online_lesson:archive

HRD Manager

ได้ HRD Staff permissions และเพิ่ม:

training_record:review
training_record:approve
training_record:reject
announcement:approve
announcement:reject
announcement:publish
announcement:schedule
announcement:unpublish
announcement:archive
announcement:restore
announcement:revision
announcement:view_history
online_lesson:approve
online_lesson:reject
online_lesson:publish
online_lesson:schedule
online_lesson:unpublish
online_lesson:archive
online_lesson:restore
online_lesson:revision
online_lesson:view_history
reports:organization_read
reports:export
reports:export_excel
reports:export_pdf
notifications:manage

Org Admin

organization:manage
organization:switch
users:read
users:create
users:update
users:delete
users:manage
employee_directory:read
employee_directory:write
permission_template:read
permission_template:assign
user_permission:read
reports:organization_read
audit_logs:read

IT Admin / Super Admin

permission_template:read
permission_template:create
permission_template:update
permission_template:clone
permission_template:delete
permission_template:assign
user_permission:read
user_permission:update
user_permission:override
user_permission:remove_override
users:manage
audit_logs:read
audit_logs:export
organization:manage
organization:switch

5. Permission Helper

สร้าง helper กลาง เช่น:

src/lib/auth/authorization.ts

ต้องมี function:

getEffectivePermissions(userId, organizationId)

hasPermission(user, permission, context?)

hasAnyPermission(user, permissions, context?)

hasAllPermissions(user, permissions, context?)

requirePermission(user, permission, context?)

requireAnyPermission(user, permissions, context?)

requireAllPermissions(user, permissions, context?)

Effective permissions ต้องคำนวณจาก:

Template permissions
+ user allow overrides
- user deny overrides
- expired overrides

เงื่อนไข:

  • deny ต้องมี priority สูงกว่า allow
  • expired permission ต้องไม่ถูกนำมาใช้
  • ต้อง scope ตาม organization
  • ต้อง cache ได้ถ้าเหมาะสม
  • ต้อง clear cache เมื่อมีการแก้ template หรือ override

6. Session / Auth Update

ปรับ session ให้รองรับ permission-first model

Session ควรมี:

userId;
organizationId;
organizationIds;
activeOrganizationId;
permissionTemplateIds;
effectivePermissions;

คง field เดิม เช่น businessRole, systemRole, membership.role ไว้ชั่วคราวเพื่อ compatibility เท่านั้น

ห้ามใช้ field เดิมเป็น source of truth ใหม่


7. Permission Template Management UI

เพิ่มหน้าจัดการ Permission Template ใน Admin

ต้องรองรับ:

  • ดูรายการ Template
  • สร้าง Template
  • แก้ไข Template
  • Clone Template
  • ลบ Template
  • Soft delete Template ที่เคยถูกใช้งาน
  • ดู Permission ภายใน Template
  • ค้นหา Permission
  • Group Permission ตาม module
  • แสดงจำนวนผู้ใช้งาน Template
  • บันทึกเหตุผลเมื่อแก้ไข
  • เก็บ audit log ทุกครั้ง

8. User Permission Assignment UI

เพิ่มหรือปรับหน้า User Management ให้รองรับ:

  • เลือก Organization
  • เลือก User
  • Assign Permission Template ให้ User
  • เปลี่ยน Template
  • แสดง Effective Permissions
  • เพิ่ม Permission เฉพาะราย
  • Deny Permission เฉพาะราย
  • Remove Override
  • กำหนดวันหมดอายุ Override ถ้ารองรับ
  • บันทึกเหตุผล
  • แสดงประวัติการเปลี่ยนสิทธิ์

Effective Permission Viewer ต้องแสดง:

Template permissions
Allow overrides
Deny overrides
Expired overrides
Final effective permissions

9. Multi-Organization Support

ระบบต้องรองรับหลายองค์กร

หลักการ:

  • Permission Template ต้องผูกกับ organization
  • User assignment ต้องผูกกับ organization
  • User override ต้องผูกกับ organization
  • Effective permissions ต้องคำนวณตาม active organization
  • การ query/write ข้อมูลต้องมี organization context
  • Super Admin / IT Admin อาจ switch organization ได้ตาม permission

ต้องตรวจสอบ:

  • organization switcher
  • membership
  • session
  • API scope
  • audit logs
  • user management
  • reports

10. Replace Server-Side Authorization

เปลี่ยน API/server guard จาก role-based เป็น permission-based

ตัวอย่าง:

เดิม:

if (!isHRD(user)) {
  return forbidden();
}

ใหม่:

await requirePermission(user, "announcement:create", {
  organizationId,
});

ต้องปรับอย่างน้อย:

  • Announcements API
  • Online Lessons API
  • Training Records API
  • Users API
  • Employee Directory API
  • Employee Import API
  • Courses API
  • Training Policy API
  • Training Matrix API
  • Reports API
  • Audit Logs API
  • Notifications API

สำคัญ:

Employee-facing API ต้อง enforce server-side scope เสมอ

announcement / online lesson:
- status = published
- is_current = true

training records:
- self-scope เท่านั้น เว้นแต่มี training_record:read_all

11. Replace Page Guards And Navigation

ปรับ page guard และ navigation ให้ใช้ permission

ตัวอย่าง:

canViewUsers = hasPermission(user, "users:read");

canViewPendingReview = hasAnyPermission(user, [
  "training_record:review",
  "announcement:approve",
  "online_lesson:approve",
]);

ห้ามใช้:

businessRole === "HRD";
isHRD();
isIT();

เป็นตัวตัดสินหลักอีกต่อไป


12. Feature UI Permission Visibility

ปรับ component ให้รับ permission context หรือ effective permissions

ตัวอย่าง:

  • ปุ่ม Create แสดงเมื่อมี announcement:create
  • ปุ่ม Submit แสดงเมื่อมี announcement:submit
  • ปุ่ม Approve แสดงเมื่อมี announcement:approve
  • ปุ่ม Publish แสดงเมื่อมี announcement:publish
  • ปุ่ม Schedule แสดงเมื่อมี announcement:schedule
  • ปุ่ม Archive แสดงเมื่อมี announcement:archive

แต่ต้องจำไว้ว่า UI visibility ไม่ใช่ security

Server/API ต้องตรวจ permission ซ้ำเสมอ


13. Audit Log

ทุก action ต่อไปนี้ต้องมี audit log:

  • Create template
  • Update template
  • Clone template
  • Delete template
  • Assign template to user
  • Change user template
  • Add user permission override
  • Deny user permission
  • Remove override
  • Organization switch ที่สำคัญ
  • Permission-based workflow actions เช่น approve, publish, archive

Audit payload ควรเก็บ:

actor_user_id
organization_id
target_user_id
target_template_id
action
before
after
reason
timestamp

14. Backward Compatibility

ห้ามลบ logic เดิมทันที

ให้ทำ compatibility layer เช่น:

mapLegacyRoleToPermissionTemplate();
resolveEffectivePermissionsFromLegacyRole();

เป้าหมายคือ:

  • ระบบเดิมไม่พัง
  • migration ทำเป็น phase ได้
  • ค่อย ๆ ลดการใช้ businessRole, systemRole, membership.role
  • ห้ามเขียน feature ใหม่โดยใช้ role-based authorization

15. Testing Checklist

ต้องทดสอบอย่างน้อย:

Employee

  • เห็นเฉพาะข้อมูลตัวเอง
  • เห็นเฉพาะ published content
  • เข้า draft ผ่าน URL ตรงไม่ได้
  • approve ไม่ได้
  • publish ไม่ได้

HRD Staff Template

  • สร้าง draft ได้
  • แก้ draft ได้
  • submit ได้
  • preview ได้
  • approve ไม่ได้
  • publish ไม่ได้
  • schedule ไม่ได้
  • archive ไม่ได้

HRD Manager Template

  • approve ได้
  • reject ได้
  • publish ได้
  • schedule ได้
  • archive ได้
  • revision ได้
  • export report ได้

IT Admin

  • สร้าง template ได้
  • แก้ template ได้
  • clone template ได้
  • ลบ template ได้ตามเงื่อนไข
  • assign template ให้ user ได้
  • override permission รายบุคคลได้
  • ดู effective permissions ได้
  • audit log ถูกบันทึกครบ

Multi-Organization

  • User คนเดียวมีสิทธิ์ต่างกันในแต่ละ organization ได้
  • active organization เปลี่ยนแล้ว permission เปลี่ยนตาม
  • API ไม่ดึงข้อมูลข้าม organization
  • audit log ระบุ organization ถูกต้อง

16. Documentation

หลังแก้ไขเสร็จ ให้สร้างเอกสารไว้ที่:

docs/permission-template-authorization-implementation.md

เอกสารต้องมี:

  • สรุปสิ่งที่แก้ไข
  • โครงสร้าง Permission-first model
  • Permission catalog
  • Default permission templates
  • Database/schema ที่เพิ่มหรือแก้ไข
  • วิธีคำนวณ effective permissions
  • วิธี assign template ให้ user
  • วิธี override permission รายบุคคล
  • วิธีรองรับหลายองค์กร
  • API/page ที่เปลี่ยนแล้ว
  • compatibility layer ที่ยังเหลือ
  • test checklist
  • known issues
  • next steps

Acceptance Criteria

งานนี้ถือว่าเสร็จเมื่อ:

  • Permission เป็น source of truth
  • Role ไม่ใช่ตัวกำหนดสิทธิ์หลักอีกต่อไป
  • มี permission catalog กลาง
  • มี Permission Template ที่จัดการผ่าน Admin ได้
  • สร้าง/แก้ไข/Clone/ลบ Template ได้
  • Assign Template ให้ User ได้
  • Override Permission รายบุคคลได้
  • รองรับหลายองค์กร
  • Effective permissions คำนวณถูกต้อง
  • API/server ใช้ requirePermission() เป็นหลัก
  • Navigation/page guard ใช้ permission
  • Employee เห็นเฉพาะข้อมูลที่ควรเห็น
  • HRD Staff publish/approve ไม่ได้
  • HRD Manager publish/approve ได้
  • IT Admin จัดการ Template และ Permission ได้
  • ทุกการเปลี่ยนสิทธิ์มี audit log
  • มีเอกสารสรุปใน docs
  • ระบบเดิมไม่พังระหว่าง migration

Important Notes

  • ห้ามใช้ Role เป็น source of truth
  • ห้าม hard-code role ใน feature ใหม่
  • ห้ามตรวจสิทธิ์เฉพาะ UI
  • Server/API ต้องตรวจ permission เสมอ
  • Permission Template คือชุดสิทธิ์ต้นแบบ ไม่ใช่ตัวตัดสินสิทธิ์
  • User Permission Override ต้องมีผลต่อ effective permissions
  • Multi-Organization ต้องไม่ทำให้ข้อมูลข้ามองค์กรรั่ว
  • ต้อง reuse pattern เดิมของโปรเจกต์ก่อนสร้างของใหม่
  • ต้องทำ migration แบบปลอดภัยและมี compatibility layer