25 KiB
Role & Permission Management Plan
วันที่อัปเดต: 2026-07-07
1. Objective
วางแผนพัฒนาหน้า Role & Permission Management สำหรับระบบ TMS โดยย้ายการจัดการสิทธิ์ไปสู่ permission-first model ที่ใช้ Permission Template เป็นแกนหลัก และยังคง compatibility กับระบบ role-based เดิมในช่วง migration
เป้าหมายของเอกสารนี้:
- กำหนดขอบเขตหน้าจัดการ Permission Template
- กำหนดขอบเขตหน้าจัดการ Permission Matrix
- กำหนดขอบเขตหน้าจัดการสิทธิ์รายผู้ใช้
- กำหนดแนวทางหน้า Audit Log สำหรับ permission changes
- สรุป schema, route, UI, และ migration work ที่ต้องทำใน coding phase ถัดไป
2. Current System Findings
จากการตรวจของจริงในโปรเจกต์ พบว่า authorization ตอนนี้เป็น hybrid model:
- session เริ่มรองรับ
effectivePermissionsแล้วใน src/auth.ts - มี permission helper ใหม่ใน src/lib/auth/authorization.ts และ src/lib/auth/session.ts
- แต่ navigation และหลาย feature ยังพึ่ง
businessRole,isHRD(),isIT()อยู่ เช่น src/config/nav-config.ts และ src/hooks/use-nav.ts - page guards หลักยังเป็น
requireHRD(),requireIT(),requireUserManagementAccess()ใน src/lib/auth/page-guards.ts - user management ปัจจุบันเปิดผ่าน
requireUserManagementAccess()และยังผูกกับ logic IT/business role ที่ src/app/api/users/route.ts - audit log ปัจจุบันมีระบบกลางอยู่แล้วใน src/features/audit-logs/server/audit-service.ts แต่ยังไม่มี action/module สำหรับ permission management โดยเฉพาะ
สรุปสั้น ๆ:
- foundation ฝั่ง permission model เริ่มมีแล้ว
- management UI ยังไม่มี
- route/API สำหรับ permission template และ user assignment ยังไม่มี
- nav และ feature access หลายส่วนยังไม่ย้ายตาม model ใหม่
3. Existing Files / Modules Related to Role & Permission
Auth / Session / RBAC
- src/auth.ts
- src/lib/auth/roles.ts
- src/lib/auth/permissions.ts
- src/lib/auth/authorization.ts
- src/lib/auth/session.ts
- src/lib/auth/page-guards.ts
- src/types/next-auth.d.ts
- src/types/index.ts
Navigation
Database / Schema
ตารางที่เกี่ยวข้อง:
usersorganizationsmembershipspermission_templatespermission_template_permissionsuser_permission_template_assignmentsuser_permission_overridespermission_audit_logsaudit_logs
Existing Pages / Features ที่ควรเป็นต้นแบบ
- Users listing page: src/app/dashboard/users/page.tsx
- Audit log page: src/app/dashboard/audit-logs/page.tsx
- Audit log feature: src/features/audit-logs/components/audit-log-listing.tsx
- Users feature: src/features/users/components/user-listing.tsx
Shared UI / Form / Table Components
DataTablestack insrc/components/ui/table/*Dialogin src/components/ui/dialog.tsxSheetin src/components/ui/sheet.tsxAlertDialogin src/components/ui/alert-dialog.tsxButtonin src/components/ui/button.tsxBadgein src/components/ui/badge.tsx- TanStack Form wrapper in src/components/ui/tanstack-form.tsx
4. Proposed Permission Model
หลักการเป้าหมาย:
Organization
-> Permission Template
-> Template Permissions
-> User Assignment
-> User Overrides
-> Effective Permissions
กติกาที่ต้องใช้กับหน้า management:
- ผู้ใช้ 1 คนต่อ 1 organization ต้องมี active template ได้เพียง 1 template
- ผู้ใช้สามารถมี extra permission รายบุคคลได้
- ผู้ใช้สามารถมี deny override ได้
- effective permissions ต้องคำนวณจาก:
- template permissions
- allow overrides
- deny overrides
- ignore expired overrides
systemRole = super_adminยังเป็น system-level override ชั่วคราว
ข้อสังเกตจาก schema ปัจจุบัน:
- requirement บอกว่า 1 user มีได้ 1 template
- แต่ src/db/schema.ts ตอนนี้ยังอนุญาตหลาย assignment ได้ ตราบใดที่
template_idต่างกัน - coding phase ถัดไปควรเปลี่ยนเป็น constraint ระดับ
(organization_id, user_id)สำหรับ active assignment เดียว หรือใช้ partial unique index ถ้าระบบยังต้องเก็บ history
5. Proposed Pages
5.1 Permission Template Management
เส้นทางที่เสนอ:
/dashboard/permissions/templates
หน้าที่:
- แสดงรายการ template ทั้งหมดของ active organization
- แสดงสถานะ
system,default,active,inactive - แสดงจำนวนผู้ใช้ที่ถูก assign อยู่
- เปิด dialog/sheet สำหรับ create
- เปิด detail/edit page หรือ sheet สำหรับแก้ไข permissions
- clone template
- deactivate template
- soft delete template ที่ไม่ใช่ system default
ฟิลด์สำคัญที่ต้องแสดง:
namecodedescriptionisSystemisDefaultisActiveassignedUserCountupdatedAtupdatedBy
ข้อกำหนด:
- ห้าม delete hard-delete
- ห้าม deactivate หรือ delete template ระบบ ถ้าจะกันเด็ดขาดให้ทำที่ server
- จำกัดสิทธิ์เฉพาะ super admin
5.2 Permission Matrix Page
เส้นทางที่เสนอ:
/dashboard/permissions/matrix
หน้าที่:
- แสดง permission catalog แบบ grouped by module
- แสดง matrix module x action
- ใช้เป็น reference screen และ editor input สำหรับ template form
กลุ่ม module เริ่มต้น:
- Dashboard
- Training Records
- Online Lessons
- Announcements
- Employees
- Courses
- Training Matrix
- Reports
- Audit Logs
- Organizations
- Permission Management
- Notifications
action groups เริ่มต้น:
- View
- Create
- Edit
- Delete
- Submit
- Approve
- Reject
- Publish
- Archive
- Export
- Manage
ข้อเสนอ UI:
- แสดง grouped card/list ด้านซ้าย
- ด้านขวาเป็น checklist permissions
- รองรับ search permission
- แสดง code จริง เช่น
training_record:approve
5.3 User Permission Assignment
เส้นทางที่เสนอ:
/dashboard/permissions/users
หน้าที่:
- ค้นหา user
- แสดง employee code, name, department, position
- assign template ได้ 1 รายการ
- เพิ่ม extra permission รายบุคคล
- deny permission รายบุคคล
- ลบ override
- preview final effective permissions
- แสดง template ปัจจุบัน
- แสดงประวัติการเปลี่ยนล่าสุด
ข้อกำหนด:
- ใช้ active organization เป็น scope เสมอ
- การบันทึกต้องทำแบบ transactional
- จำกัดสิทธิ์เฉพาะ super admin
5.4 Permission Audit Log
เส้นทางที่เสนอ:
/dashboard/permissions/audit-logs
หน้าที่:
- ค้นหาประวัติการเปลี่ยน permission
- filter ตาม actor, target user, template, action, date range
- ดู before/after payload
- ดูเหตุผลการเปลี่ยน
หมายเหตุ:
- สามารถ reuse audit log table pattern เดิมจาก audit-logs feature ได้
- แต่ data source ควรอ่านจาก
permission_audit_logsโดยตรง หรือทำ unified view ในภายหลัง
6. Proposed Database / Schema Changes
รอบ implement ถัดไปควรแก้ schema เพิ่มจากของปัจจุบันดังนี้:
- Tighten assignment constraint
- เปลี่ยน
user_permission_template_assignmentsให้รองรับ active assignment เดียวต่อ(organization_id, user_id) - ถ้าต้องเก็บ history ให้ใช้
is_active+ partial unique index
- Assignment history strategy
- ถ้าต้องเปลี่ยน template ให้ deactivate row เดิมก่อน แล้วสร้าง row ใหม่
- หลีกเลี่ยง update ทับเพื่อไม่เสีย audit trail
- Override semantics
- คง
effect = allow|deny - ใช้
is_active,expires_at,revoked_at,revoked_by
- Permission template lifecycle
- คง
deleted_atสำหรับ soft delete - ใช้
is_activeสำหรับ deactivate
- Permission audit detail
- พิจารณาเพิ่ม
organization_id + action + created_atindexes ถ้าข้อมูลโต - พิจารณาเพิ่ม
target_template_codeหรือtarget_template_name_snapshotถ้าต้องการอ่าน log ย้อนหลังง่ายขึ้น
7. Proposed API Routes
Permission Templates
GET /api/permission-templatesPOST /api/permission-templatesGET /api/permission-templates/[id]PATCH /api/permission-templates/[id]POST /api/permission-templates/[id]/clonePOST /api/permission-templates/[id]/deactivatePOST /api/permission-templates/[id]/activateDELETE /api/permission-templates/[id]
Permission Matrix / Catalog
GET /api/permissions/catalog
User Permission Assignments
GET /api/user-permissionsGET /api/user-permissions/[userId]PUT /api/user-permissions/[userId]/assignmentPOST /api/user-permissions/[userId]/overridesPATCH /api/user-permissions/[userId]/overrides/[overrideId]DELETE /api/user-permissions/[userId]/overrides/[overrideId]GET /api/user-permissions/[userId]/effective
Permission Audit Logs
GET /api/permission-audit-logs
ทุก route ต้อง:
- ใช้
requireSession()+ super-admin gate - scope ด้วย active organization
- validate payload ด้วย Zod
- เขียน audit log ทุกครั้งที่มีการเปลี่ยน template/assignment/override
8. Proposed UI Components
Feature module ที่เสนอ
src/features/permission-management/
api/
types.ts
service.ts
queries.ts
mutations.ts
components/
permission-template-listing.tsx
permission-template-table.tsx
permission-template-columns.tsx
permission-template-form-sheet.tsx
permission-matrix.tsx
user-permission-assignment-listing.tsx
user-permission-assignment-form.tsx
permission-effective-preview.tsx
permission-audit-log-listing.tsx
schemas/
permission-template.ts
user-permission-assignment.ts
server/
permission-template-data.ts
user-permission-data.ts
permission-audit-data.ts
Shared components ที่ควร reuse
DataTableสำหรับ template list และ permission audit logSheetหรือDialogสำหรับ create/edit templateAlertDialogสำหรับ deactivate / soft delete confirmationBadgeสำหรับ status เช่นSystem,Default,Active,InactiveuseAppFormผ่านtanstack-form.tsx
UI decisions ที่แนะนำ
- Template list ใช้ table
- Template edit ใช้ sheet เพราะมี permission checklist ยาว
- Permission matrix ใช้ accordion/group sections
- User assignment ใช้ split layout:
- ซ้ายเป็น user summary + template selector
- ขวาเป็น extra/deny overrides + effective preview
9. Access Control Rules
กติกาเป้าหมายของหน้าชุดนี้:
- Super Admin เท่านั้นที่เข้าหน้า permission management ได้
- Admin, HRD, Employee ห้ามเข้าทั้ง page และ API
- nav item ต้องซ่อนสำหรับ non-super-admin
- route handler ต้อง enforce ซ้ำเสมอ
กติกา permission ที่เสนอ:
permission_template:readpermission_template:createpermission_template:updatepermission_template:clonepermission_template:deletepermission_template:assignuser_permission:readuser_permission:updateuser_permission:overrideuser_permission:remove_override
ข้อเสนอสำหรับ phase implement:
- ระยะสั้นให้ super admin gate เป็นหลัก
- ระยะถัดไปค่อย map ว่า super admin ต้องถือ permission เหล่านี้ใน template ด้วยหรือไม่
10. Audit Log Strategy
ของเดิม:
- มี
audit_logsและlogAuditEvent()อยู่แล้ว - มี audit log UI/read model อยู่แล้วใน feature
audit-logs
สิ่งที่ควรทำสำหรับ permission management:
- ใช้
permission_audit_logsเป็น source หลักของ domain นี้ - เพิ่ม action catalog เช่น:
TEMPLATE_CREATETEMPLATE_UPDATETEMPLATE_CLONETEMPLATE_DEACTIVATETEMPLATE_ACTIVATETEMPLATE_SOFT_DELETEUSER_TEMPLATE_ASSIGNUSER_TEMPLATE_CHANGEUSER_OVERRIDE_ALLOWUSER_OVERRIDE_DENYUSER_OVERRIDE_REMOVE
payload ที่ควรเก็บ:
organizationIdactorUserIdtargetUserIdtemplateIdassignmentIdoverrideIdactionreasonbeforeaftercreatedAt
ข้อเสนอ implementation:
- เขียน helper ใหม่เฉพาะ permission domain เช่น
logPermissionAuditEvent() - ภายในอาจ reuse pattern จาก
logAuditEvent()
11. Migration Strategy from Role-based to Permission-first
ระยะ migration ควรแบ่งเป็น 2 track:
Track A: Management surfaces
- สร้าง feature permission management ให้เสร็จก่อน
- เปิดใช้เฉพาะ super admin
- เริ่ม assign template จริงให้ผู้ใช้
Track B: Runtime authorization cleanup
- ค่อย ๆ เปลี่ยน nav, page guards, และ feature checks จาก
businessRoleไปเป็น permission - เริ่มจาก features สำคัญ:
- users
- audit logs
- announcements
- online lessons
- training records
compatibility rules:
- ยังไม่ลบ
businessRole - ยังไม่ลบ
isHRD(),isIT() - session ยัง fallback ไป
memberships.permissionsหรือ default role permissions ได้ - feature ใหม่ห้ามสร้างบน role-based gate
12. Implementation Phases
Phase 1: Planning and contracts
- เอกสารแผนนี้
- ยืนยัน route names, page names, permission groups
Phase 2: Schema tightening
- ปรับ assignment constraint ให้เหลือ 1 active template ต่อ user/org
- เพิ่ม indexes ที่จำเป็น
- เตรียม seed strategy สำหรับ default templates
Phase 3: Server-side domain
- สร้าง feature
permission-management - เพิ่ม server helpers สำหรับ template CRUD, assignment, override, effective preview
- เพิ่ม audit log helper ของ permission domain
Phase 4: API routes
- เพิ่ม route handlers ทั้งหมดสำหรับ template, assignment, audit
- ผูก super-admin-only access
Phase 5: UI pages
- Template management page
- Matrix page
- User assignment page
- Permission audit log page
Phase 6: Navigation and guards
- เพิ่ม nav item ใหม่สำหรับ permission management
- ผูกกับ permission หรือ super-admin gate
Phase 7: Runtime migration follow-up
- ค่อย ๆ ย้าย feature gates ที่ยังใช้
businessRole
13. Validation & Testing Checklist
Access
- Super admin เข้าหน้า permission management ได้
- non-super-admin เข้า page ไม่ได้
- non-super-admin เรียก API ไม่ได้
Templates
- สร้าง template ได้
- clone template ได้
- แก้ไข template ได้
- deactivate template ได้
- soft delete template ได้
- system template ถูกป้องกันการลบ
Assignments
- user 1 คน assign active template ได้เพียง 1 template ต่อ organization
- เปลี่ยน template แล้วของเดิมถูก deactivate
- preview effective permissions ถูกต้อง
Overrides
- allow override ทำงานถูกต้อง
- deny override override สิทธิ์จาก template ได้
- remove override ได้
- expired override ไม่ถูกนับ
Audit
- ทุก action สำคัญมี permission audit log
- before/after payload อ่านได้
- filter log ได้ตาม actor/target/action/date
Compatibility
- ผู้ใช้เดิมที่ยังไม่มี template ยังใช้งานระบบได้ผ่าน fallback
- หน้าเดิมไม่พังระหว่าง migration
14. Risks / Edge Cases
- Current schema กับ requirement ยังไม่ตรงกัน
ตอนนี้ assignment table ยังเปิดโอกาสให้หลาย template active พร้อมกันได้ ถ้าไม่ tighten constraint ก่อน UI จะทำให้ data model สับสน
- Hybrid authorization ช่วงเปลี่ยนผ่าน
บาง feature ใช้ effectivePermissions แล้ว แต่ nav/page/API จำนวนมากยังพึ่ง businessRole
- Multi-organization scope
ทุกหน้า permission management ต้องใช้ active organization ชัดเจน ไม่เช่นนั้นอาจ assign template ข้ามองค์กรผิดได้
- Super admin without membership
ระบบปัจจุบันยังมี flow ที่ super admin สามารถเข้าถึงหลายองค์กรได้แม้ไม่มี membership แบบปกติ จึงต้องระวัง context ตอน create/update permission data
- Template deactivation edge case
ถ้า deactivate template ที่ยังมีผู้ใช้ active อยู่ ต้องกำหนดกติกาชัดว่า:
- ห้าม deactivate
- หรืออนุญาต แต่ต้องเตือนว่าผู้ใช้จะ fallback ไปสิทธิ์เดิม
ข้อเสนอคือห้าม deactivate ถ้ายังมี active assignments อยู่ เว้นแต่เป็น explicit admin action พร้อม reason
- Permission catalog drift
ถ้ามีการเพิ่ม permission ใหม่ใน permissions.ts แต่ไม่อัปเดต matrix/UI/template seeds จะทำให้ template ไม่ครบ
15. Files Expected to be Created or Modified
New docs
docs/role-permission-management-plan.md
New pages
src/app/dashboard/permissions/templates/page.tsxsrc/app/dashboard/permissions/matrix/page.tsxsrc/app/dashboard/permissions/users/page.tsxsrc/app/dashboard/permissions/audit-logs/page.tsx
New API routes
src/app/api/permission-templates/route.tssrc/app/api/permission-templates/[id]/route.tssrc/app/api/permission-templates/[id]/clone/route.tssrc/app/api/permission-templates/[id]/activate/route.tssrc/app/api/permission-templates/[id]/deactivate/route.tssrc/app/api/user-permissions/route.tssrc/app/api/user-permissions/[userId]/route.tssrc/app/api/user-permissions/[userId]/assignment/route.tssrc/app/api/user-permissions/[userId]/overrides/route.tssrc/app/api/user-permissions/[userId]/overrides/[overrideId]/route.tssrc/app/api/user-permissions/[userId]/effective/route.tssrc/app/api/permission-audit-logs/route.tssrc/app/api/permissions/catalog/route.ts
New feature module
src/features/permission-management/**
Existing files likely to be updated
src/config/nav-config.tssrc/hooks/use-nav.tssrc/lib/auth/page-guards.tssrc/lib/auth/session.tssrc/lib/auth/permissions.tssrc/lib/auth/authorization.tssrc/features/audit-logs/server/audit-service.tssrc/types/index.ts
Schema and migration files for later phase
src/db/schema.tsdrizzle/*.sql
Recommendation
ถ้าจะเริ่ม coding phase จากแผนนี้ จุดเริ่มที่ปลอดภัยที่สุดคือ:
- Tighten schema ให้ user มี active template เดียวต่อ organization
- ทำ server layer ของ permission-management ก่อน UI
- เปิดหน้า Template Management ก่อนหน้า User Assignment
- ค่อยเพิ่ม Permission Audit Log page เป็นลำดับถัดไป
แนวทางนี้จะทำให้ model แน่นก่อน แล้ว UI จะไม่ต้องย้อนแก้ภายหลัง