10 KiB
Permission Template Authorization Implementation
วันที่อัปเดต: 2026-07-07
Scope ของเฟสแรก
เฟสแรกของงาน permission-authorization เน้นวาง foundation ให้ระบบย้ายจาก role-based authorization ไปสู่ permission-first model แบบค่อยเป็นค่อยไป โดยยังไม่บังคับเปลี่ยนทุก feature พร้อมกันในครั้งเดียว
สิ่งที่ทำในเฟสนี้:
- เพิ่ม permission catalog กลาง
- เพิ่ม helper สำหรับเช็ก permission แบบ type-safe
- ผูก default permission ของ membership เข้ากับ catalog กลาง
- เพิ่ม session helper สำหรับ
requirePermission()/requireAnyPermission()/requireAllPermissions() - เชื่อม
src/auth.tsให้ resolve effective permissions จาก template assignment และ override - ขยาย session payload ให้มี
effectivePermissionsและpermissionTemplateIds - เพิ่ม schema และ migration สำหรับ permission template, assignment, override, และ audit log
โครงสร้าง Permission-first Model
โครงสร้างเป้าหมายของระบบ:
Organization
-> Permission Template
-> Template Permissions
-> User Template Assignments
-> User Permission Overrides
-> Effective Permissions
หลักการในเฟสนี้:
Permissionคือ source of truth ใหม่membership.roleยังอยู่เพื่อ compatibility ระหว่าง migrationbusinessRole,isHRD(),isIT()ยังไม่ถูกลบทิ้ง แต่ไม่ควรเป็นฐานของ feature ใหม่super_adminยังเป็น system-level bypass ได้ตาม helper ปัจจุบัน
Permission Catalog
ไฟล์หลัก:
สิ่งที่เพิ่ม:
Permissiontype แบบรวมค่า permission ทั้งระบบ- permission catalog แยกตาม module
- default permission set สำหรับ
owner,admin,member - helper:
hasPermission()hasAnyPermission()hasAllPermissions()normalizePermissions()isPermission()
Default Permission Mapping
ไฟล์ที่ผูก default mapping:
สถานะปัจจุบัน:
getDefaultPermissionsForRole()ถูกเปลี่ยนให้ดึงจาก catalog กลางแล้ว- ระบบเดิมยังสามารถสร้าง default permissions จาก membership role ได้เหมือนเดิม
- ยังไม่ได้ย้ายไปใช้ seeded permission templates จริงในฐานข้อมูล
Session และ Authorization Helper
ไฟล์หลัก:
สิ่งที่เพิ่ม:
resolveEffectivePermissions()ถูกใช้ใน session callback แล้วrequirePermission(permission)requireAnyPermission(permissions)requireAllPermissions(permissions)- nav access metadata รองรับ
Permissiontype มากขึ้น
ข้อสำคัญ:
- session จะพยายามอ่านสิทธิ์จาก:
- active permission template assignments
- active user permission overrides
- fallback membership permissions หรือ default role permissions
session.user.permissionsและsession.user.effectivePermissionsตอนนี้ชี้ไปที่ผลลัพธ์ effective permissions ชุดเดียวกันrequireOrganizationAccess()และrequirePermission()เปลี่ยนมาอ้างsession.user.effectivePermissionsเป็นหลักแล้ว
Database / Schema ที่เพิ่ม
ไฟล์หลัก:
ตารางและ enum ที่เพิ่ม:
-
permission_override_effectใช้เก็บค่าallowและdeny -
permission_templatesเก็บ template รายองค์กร
คอลัมน์สำคัญ:
organization_idcodenamedescriptionis_systemis_defaultis_activedeleted_at
-
permission_template_permissionsเก็บรายการ permission ของแต่ละ template -
user_permission_template_assignmentsเก็บการ assign template ให้ user แบบผูกกับ organization
หมายเหตุ:
- รองรับหลาย template ต่อ user ต่อ organization ได้
- มี
is_activeสำหรับรองรับการปิด assignment โดยไม่ต้องลบทิ้ง
user_permission_overridesเก็บ override รายบุคคล
ความสามารถที่รองรับแล้วใน schema:
allowoverridedenyoverrideexpires_atrevoked_atrevoked_by
permission_audit_logsเก็บ audit trail สำหรับการเปลี่ยน template, assignment, override
วิธีคำนวณ Effective Permissions
logic ที่ถูกต่อเข้ากับ session แล้วในรอบนี้:
effective permissions
= permissions จาก template assignment ที่ active
+ allow overrides ที่ยังไม่หมดอายุ
- deny overrides ที่ active และยังไม่หมดอายุ
กติกาที่ต้องใช้ในเฟสถัดไป:
denyมี priority สูงกว่าallow- override ที่หมดอายุแล้วต้องไม่ถูกใช้
- ทุกการคำนวณต้องผูกกับ
active organization - ถ้า user ยังไม่มี active template assignment จะ fallback ไปที่
memberships.permissions - ถ้า membership ไม่มี permissions เลย จะ fallback ไปที่ default permissions ตาม role เดิม
ไฟล์ที่แก้ในเฟสนี้
- src/lib/auth/permissions.ts
- src/lib/auth/authorization.ts
- src/lib/auth/roles.ts
- src/auth.ts
- src/lib/auth/session.ts
- src/types/next-auth.d.ts
- src/types/index.ts
- src/db/schema.ts
- drizzle/0015_permission_template_authorization.sql
สิ่งที่ยังไม่ได้ทำ
- seed default permission templates ลงฐานข้อมูล
- helper
getEffectivePermissions(userId, organizationId) - admin UI สำหรับจัดการ template
- UI สำหรับ assign template และตั้ง override รายบุคคล
- migration ของ feature guards จาก role-based เป็น permission-based แบบครบทุกหน้า
- audit write logic ตอน create/update/assign/override
ลำดับงานถัดไปที่แนะนำ
- เพิ่ม permission template service และ effective permission resolver
- seed default permission templates และ assignment strategy สำหรับข้อมูลเดิม
- ทำ seed default templates ต่อ organization
- ย้าย page guards และ navigation ไปใช้ permission helper
- ย้าย route handlers สำคัญไปใช้
requirePermission() - ค่อยทำ admin UI สำหรับ template และ user assignment
Verification
ตรวจสอบแล้วในรอบนี้:
oxlintผ่านสำหรับไฟล์ auth/schema ที่แก้tsc --noEmitผ่านหลังเพิ่ม foundation ของ permission helpersession.user.permissionsถูกย้ายให้ใช้ผลจาก effective permission resolver แล้ว
หมายเหตุ:
- หลังเพิ่ม migration
0015ควรรันnpm run migrateในเครื่องก่อนเริ่มทำ service/UI เฟสถัดไป - ยังไม่ได้เพิ่ม snapshot ใหม่ใน
drizzle/metaเพราะรอบนี้เพิ่ม migration SQL แบบ manual เพื่อคุมผลกระทบให้แคบที่สุด