This commit is contained in:
2026-07-16 09:53:14 +07:00
parent 0fc112a2e8
commit 29cec708a3
1236 changed files with 212848 additions and 0 deletions

View File

@@ -0,0 +1,625 @@
# 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](/D:/WY-2569/HRD/training-system-minimal-refactor/src/auth.ts:254)
- มี permission helper ใหม่ใน [src/lib/auth/authorization.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/lib/auth/authorization.ts:27) และ [src/lib/auth/session.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/lib/auth/session.ts:215)
- แต่ navigation และหลาย feature ยังพึ่ง `businessRole`, `isHRD()`, `isIT()` อยู่ เช่น [src/config/nav-config.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/config/nav-config.ts:23) และ [src/hooks/use-nav.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/hooks/use-nav.ts:53)
- page guards หลักยังเป็น `requireHRD()`, `requireIT()`, `requireUserManagementAccess()` ใน [src/lib/auth/page-guards.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/lib/auth/page-guards.ts:20)
- user management ปัจจุบันเปิดผ่าน `requireUserManagementAccess()` และยังผูกกับ logic IT/business role ที่ [src/app/api/users/route.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/app/api/users/route.ts:23)
- audit log ปัจจุบันมีระบบกลางอยู่แล้วใน [src/features/audit-logs/server/audit-service.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/features/audit-logs/server/audit-service.ts:5) แต่ยังไม่มี 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](/D:/WY-2569/HRD/training-system-minimal-refactor/src/auth.ts:1)
- [src/lib/auth/roles.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/lib/auth/roles.ts:1)
- [src/lib/auth/permissions.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/lib/auth/permissions.ts:1)
- [src/lib/auth/authorization.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/lib/auth/authorization.ts:1)
- [src/lib/auth/session.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/lib/auth/session.ts:1)
- [src/lib/auth/page-guards.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/lib/auth/page-guards.ts:1)
- [src/types/next-auth.d.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/types/next-auth.d.ts:1)
- [src/types/index.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/types/index.ts:1)
### Navigation
- [src/config/nav-config.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/config/nav-config.ts:1)
- [src/hooks/use-nav.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/hooks/use-nav.ts:1)
### Database / Schema
- [src/db/schema.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/db/schema.ts:104)
- [drizzle/0015_permission_template_authorization.sql](/D:/WY-2569/HRD/training-system-minimal-refactor/drizzle/0015_permission_template_authorization.sql:1)
ตารางที่เกี่ยวข้อง:
- `users`
- `organizations`
- `memberships`
- `permission_templates`
- `permission_template_permissions`
- `user_permission_template_assignments`
- `user_permission_overrides`
- `permission_audit_logs`
- `audit_logs`
### Existing Pages / Features ที่ควรเป็นต้นแบบ
- Users listing page: [src/app/dashboard/users/page.tsx](/D:/WY-2569/HRD/training-system-minimal-refactor/src/app/dashboard/users/page.tsx:1)
- Audit log page: [src/app/dashboard/audit-logs/page.tsx](/D:/WY-2569/HRD/training-system-minimal-refactor/src/app/dashboard/audit-logs/page.tsx:1)
- Audit log feature: [src/features/audit-logs/components/audit-log-listing.tsx](/D:/WY-2569/HRD/training-system-minimal-refactor/src/features/audit-logs/components/audit-log-listing.tsx)
- Users feature: [src/features/users/components/user-listing.tsx](/D:/WY-2569/HRD/training-system-minimal-refactor/src/features/users/components/user-listing.tsx)
### Shared UI / Form / Table Components
- `DataTable` stack in `src/components/ui/table/*`
- `Dialog` in [src/components/ui/dialog.tsx](/D:/WY-2569/HRD/training-system-minimal-refactor/src/components/ui/dialog.tsx)
- `Sheet` in [src/components/ui/sheet.tsx](/D:/WY-2569/HRD/training-system-minimal-refactor/src/components/ui/sheet.tsx)
- `AlertDialog` in [src/components/ui/alert-dialog.tsx](/D:/WY-2569/HRD/training-system-minimal-refactor/src/components/ui/alert-dialog.tsx)
- `Button` in [src/components/ui/button.tsx](/D:/WY-2569/HRD/training-system-minimal-refactor/src/components/ui/button.tsx)
- `Badge` in [src/components/ui/badge.tsx](/D:/WY-2569/HRD/training-system-minimal-refactor/src/components/ui/badge.tsx)
- TanStack Form wrapper in [src/components/ui/tanstack-form.tsx](/D:/WY-2569/HRD/training-system-minimal-refactor/src/components/ui/tanstack-form.tsx)
## 4. Proposed Permission Model
หลักการเป้าหมาย:
```text
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](/D:/WY-2569/HRD/training-system-minimal-refactor/src/db/schema.ts:200) ตอนนี้ยังอนุญาตหลาย 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
ฟิลด์สำคัญที่ต้องแสดง:
- `name`
- `code`
- `description`
- `isSystem`
- `isDefault`
- `isActive`
- `assignedUserCount`
- `updatedAt`
- `updatedBy`
ข้อกำหนด:
- ห้าม 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 เพิ่มจากของปัจจุบันดังนี้:
1. Tighten assignment constraint
- เปลี่ยน `user_permission_template_assignments` ให้รองรับ active assignment เดียวต่อ `(organization_id, user_id)`
- ถ้าต้องเก็บ history ให้ใช้ `is_active` + partial unique index
2. Assignment history strategy
- ถ้าต้องเปลี่ยน template ให้ deactivate row เดิมก่อน แล้วสร้าง row ใหม่
- หลีกเลี่ยง update ทับเพื่อไม่เสีย audit trail
3. Override semantics
- คง `effect = allow|deny`
- ใช้ `is_active`, `expires_at`, `revoked_at`, `revoked_by`
4. Permission template lifecycle
- คง `deleted_at` สำหรับ soft delete
- ใช้ `is_active` สำหรับ deactivate
5. Permission audit detail
- พิจารณาเพิ่ม `organization_id + action + created_at` indexes ถ้าข้อมูลโต
- พิจารณาเพิ่ม `target_template_code` หรือ `target_template_name_snapshot` ถ้าต้องการอ่าน log ย้อนหลังง่ายขึ้น
## 7. Proposed API Routes
### Permission Templates
- `GET /api/permission-templates`
- `POST /api/permission-templates`
- `GET /api/permission-templates/[id]`
- `PATCH /api/permission-templates/[id]`
- `POST /api/permission-templates/[id]/clone`
- `POST /api/permission-templates/[id]/deactivate`
- `POST /api/permission-templates/[id]/activate`
- `DELETE /api/permission-templates/[id]`
### Permission Matrix / Catalog
- `GET /api/permissions/catalog`
### User Permission Assignments
- `GET /api/user-permissions`
- `GET /api/user-permissions/[userId]`
- `PUT /api/user-permissions/[userId]/assignment`
- `POST /api/user-permissions/[userId]/overrides`
- `PATCH /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 ที่เสนอ
```text
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 log
- `Sheet` หรือ `Dialog` สำหรับ create/edit template
- `AlertDialog` สำหรับ deactivate / soft delete confirmation
- `Badge` สำหรับ status เช่น `System`, `Default`, `Active`, `Inactive`
- `useAppForm` ผ่าน `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: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`
ข้อเสนอสำหรับ 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_CREATE`
- `TEMPLATE_UPDATE`
- `TEMPLATE_CLONE`
- `TEMPLATE_DEACTIVATE`
- `TEMPLATE_ACTIVATE`
- `TEMPLATE_SOFT_DELETE`
- `USER_TEMPLATE_ASSIGN`
- `USER_TEMPLATE_CHANGE`
- `USER_OVERRIDE_ALLOW`
- `USER_OVERRIDE_DENY`
- `USER_OVERRIDE_REMOVE`
payload ที่ควรเก็บ:
- `organizationId`
- `actorUserId`
- `targetUserId`
- `templateId`
- `assignmentId`
- `overrideId`
- `action`
- `reason`
- `before`
- `after`
- `createdAt`
ข้อเสนอ 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
1. Current schema กับ requirement ยังไม่ตรงกัน
ตอนนี้ assignment table ยังเปิดโอกาสให้หลาย template active พร้อมกันได้ ถ้าไม่ tighten constraint ก่อน UI จะทำให้ data model สับสน
2. Hybrid authorization ช่วงเปลี่ยนผ่าน
บาง feature ใช้ `effectivePermissions` แล้ว แต่ nav/page/API จำนวนมากยังพึ่ง `businessRole`
3. Multi-organization scope
ทุกหน้า permission management ต้องใช้ active organization ชัดเจน ไม่เช่นนั้นอาจ assign template ข้ามองค์กรผิดได้
4. Super admin without membership
ระบบปัจจุบันยังมี flow ที่ super admin สามารถเข้าถึงหลายองค์กรได้แม้ไม่มี membership แบบปกติ จึงต้องระวัง context ตอน create/update permission data
5. Template deactivation edge case
ถ้า deactivate template ที่ยังมีผู้ใช้ active อยู่ ต้องกำหนดกติกาชัดว่า:
- ห้าม deactivate
- หรืออนุญาต แต่ต้องเตือนว่าผู้ใช้จะ fallback ไปสิทธิ์เดิม
ข้อเสนอคือห้าม deactivate ถ้ายังมี active assignments อยู่ เว้นแต่เป็น explicit admin action พร้อม reason
6. 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.tsx`
- `src/app/dashboard/permissions/matrix/page.tsx`
- `src/app/dashboard/permissions/users/page.tsx`
- `src/app/dashboard/permissions/audit-logs/page.tsx`
### New API routes
- `src/app/api/permission-templates/route.ts`
- `src/app/api/permission-templates/[id]/route.ts`
- `src/app/api/permission-templates/[id]/clone/route.ts`
- `src/app/api/permission-templates/[id]/activate/route.ts`
- `src/app/api/permission-templates/[id]/deactivate/route.ts`
- `src/app/api/user-permissions/route.ts`
- `src/app/api/user-permissions/[userId]/route.ts`
- `src/app/api/user-permissions/[userId]/assignment/route.ts`
- `src/app/api/user-permissions/[userId]/overrides/route.ts`
- `src/app/api/user-permissions/[userId]/overrides/[overrideId]/route.ts`
- `src/app/api/user-permissions/[userId]/effective/route.ts`
- `src/app/api/permission-audit-logs/route.ts`
- `src/app/api/permissions/catalog/route.ts`
### New feature module
- `src/features/permission-management/**`
### Existing files likely to be updated
- `src/config/nav-config.ts`
- `src/hooks/use-nav.ts`
- `src/lib/auth/page-guards.ts`
- `src/lib/auth/session.ts`
- `src/lib/auth/permissions.ts`
- `src/lib/auth/authorization.ts`
- `src/features/audit-logs/server/audit-service.ts`
- `src/types/index.ts`
### Schema and migration files for later phase
- `src/db/schema.ts`
- `drizzle/*.sql`
## Recommendation
ถ้าจะเริ่ม coding phase จากแผนนี้ จุดเริ่มที่ปลอดภัยที่สุดคือ:
1. Tighten schema ให้ user มี active template เดียวต่อ organization
2. ทำ server layer ของ permission-management ก่อน UI
3. เปิดหน้า Template Management ก่อนหน้า User Assignment
4. ค่อยเพิ่ม Permission Audit Log page เป็นลำดับถัดไป
แนวทางนี้จะทำให้ model แน่นก่อน แล้ว UI จะไม่ต้องย้อนแก้ภายหลัง