ADR-006 - ระบบการอนุญาตโมดูล
ADR-006: ระบบการอนุญาตโมดูล
หัวข้อที่มีชื่อว่า “ADR-006: ระบบการอนุญาตโมดูล”ระบบการอนุญาตแบบลำดับชั้นอย่างละเอียดสำหรับโมดูล XOOPS ช่วยให้สามารถควบคุมการเข้าถึงแบบละเอียดได้
ยอมรับแล้ว - นำไปใช้ใน XOOPS 2.5.x และขยายใน XOOPS 4.0
คำชี้แจงปัญหา
หัวข้อที่มีชื่อว่า “คำชี้แจงปัญหา”โมดูล XOOPS ต้องการการควบคุมสิทธิ์ที่ยืดหยุ่นที่อนุญาต:
- สิทธิ์ระดับโมดูล - ผู้ใช้สามารถเข้าถึงโมดูลนี้ได้หรือไม่
- สิทธิ์ระดับออบเจ็กต์ - ผู้ใช้สามารถเข้าถึงรายการเฉพาะนี้ได้หรือไม่
- สิทธิ์ระดับการดำเนินการ - ผู้ใช้สามารถดำเนินการนี้ได้หรือไม่
- สิทธิ์ที่กำหนดเอง - โมดูลสามารถกำหนดการอนุญาตของตนเองได้หรือไม่
สถานะปัจจุบัน
หัวข้อที่มีชื่อว่า “สถานะปัจจุบัน”XOOPS 2.5 ใช้ระบบ XoopsGroupPermission:
<?php$perm_handler = xoops_getHandler('groupperm');$isAllowed = $perm_handler->checkRight( 'modulename', 'action', $itemId, $groupId);ความท้าทาย
หัวข้อที่มีชื่อว่า “ความท้าทาย”- การสืบค้นที่ซับซ้อน - การตรวจสอบสิทธิ์จำเป็นต้องรวมฐานข้อมูล
- ลำดับชั้นที่จำกัด - สร้างกลุ่มสิทธิ์ได้ยาก
- การแคชไม่ดี - ไม่มีการแคชสิทธิ์ในตัว
- รูปแบบโมดูล - แต่ละโมดูลมีการใช้งานที่แตกต่างกัน
- ประสิทธิภาพ - คำขอ DB หลายรายการสำหรับการตรวจสอบสิทธิ์
การตัดสินใจ
หัวข้อที่มีชื่อว่า “การตัดสินใจ”ใช้ระบบการอนุญาตแบบลำดับชั้น
หัวข้อที่มีชื่อว่า “ใช้ระบบการอนุญาตแบบลำดับชั้น”สร้างระบบอนุญาตแคชที่ได้มาตรฐานซึ่งสนับสนุน:
- สิทธิ์แบบลำดับชั้น - การสืบทอดจากกลุ่มหลัก
- การเข้าถึงตามบทบาท - แมปการอนุญาตสำหรับบทบาท (ผู้ดูแลระบบ ผู้ดูแล ผู้ใช้ แขก)
- การอนุญาตวัตถุ - การควบคุมแบบละเอียดต่อรายการ
- แคช - สิทธิ์แคชเพื่อลดการสืบค้น
- สิทธิ์ที่กำหนดเอง - โมดูลกำหนดสิทธิ์ของตนเอง
- เส้นทางการตรวจสอบ - การเปลี่ยนแปลงการอนุญาตบันทึก
ลำดับชั้นการอนุญาต
หัวข้อที่มีชื่อว่า “ลำดับชั้นการอนุญาต”User └── Group 1 (Admin) └── Permission: admin_module └── Permission: edit_all_items └── Permission: delete_all_items └── Group 2 (Moderator) └── Permission: moderate_comments └── Permission: edit_own_items └── Group 3 (User) └── Permission: view_published_items └── Permission: edit_own_items └── Group 4 (Guest) └── Permission: view_published_itemsสถาปัตยกรรม
หัวข้อที่มีชื่อว่า “สถาปัตยกรรม”mermaidgraph TB subgraph "Permission System" A["Permission Registry<br/>(Define permissions)"] B["Permission Checker<br/>(Check access)"] C["Permission Cache<br/>(Improve performance)"] D["Permission Audit Log<br/>(Track changes)"] end
subgraph "Data Layer" E["Group Permissions Table"] F["User Groups Table"] G["Permission Definitions"] end
A --> E B --> E B --> C C --> E D --> E F --> Bส่วนประกอบหลัก
หัวข้อที่มีชื่อว่า “ส่วนประกอบหลัก”1. คำจำกัดความของการอนุญาต
หัวข้อที่มีชื่อว่า “1. คำจำกัดความของการอนุญาต”<?php// Module defines its permissions in xoops_version.php
$modversion['permissions'] = [ [ 'name' => 'module_view', 'description' => 'Can view module', 'level' => 'module', ], [ 'name' => 'item_view', 'description' => 'Can view items', 'level' => 'item', ], [ 'name' => 'item_create', 'description' => 'Can create items', 'level' => 'item', ], [ 'name' => 'item_edit', 'description' => 'Can edit items', 'level' => 'item', ], [ 'name' => 'item_delete', 'description' => 'Can delete items', 'level' => 'item', ], [ 'name' => 'admin_manage', 'description' => 'Can manage module', 'level' => 'admin', ],];
// Default permissions by group$modversion['group_permissions'] = [ // Admin group gets all permissions '1' => [ 'module_view' => 1, 'item_view' => 1, 'item_create' => 1, 'item_edit' => 1, 'item_delete' => 1, 'admin_manage' => 1, ], // User group '3' => [ 'module_view' => 1, 'item_view' => 1, 'item_create' => 1, 'item_edit' => 0, 'item_delete' => 0, 'admin_manage' => 0, ], // Guest group '4' => [ 'module_view' => 1, 'item_view' => 1, 'item_create' => 0, 'item_edit' => 0, 'item_delete' => 0, 'admin_manage' => 0, ],];2. ตัวตรวจสอบการอนุญาต
หัวข้อที่มีชื่อว่า “2. ตัวตรวจสอบการอนุญาต”<?phpdeclare(strict_types=1);
namespace XoopsCore\Permission;
class PermissionChecker{ private PermissionCache $cache; private PermissionRepository $repository;
public function hasPermission( User $user, string $permissionName, ?int $itemId = null ): bool { // Check cache first $cacheKey = "perm_{$user->getId()}_{$permissionName}_{$itemId}"; if ($this->cache->has($cacheKey)) { return $this->cache->get($cacheKey); }
$hasPermission = false;
// Check all user groups foreach ($user->getGroups() as $group) { if ($this->checkGroupPermission($group, $permissionName, $itemId)) { $hasPermission = true; break; } }
// Cache result $this->cache->set($cacheKey, $hasPermission, 3600);
// Log high-level access checks if ($hasPermission && $this->shouldAuditLog($permissionName)) { $this->auditLog('PERMISSION_CHECKED', [ 'user_id' => $user->getId(), 'permission' => $permissionName, 'item_id' => $itemId, 'result' => 'ALLOWED', ]); }
return $hasPermission; }
private function checkGroupPermission( Group $group, string $permissionName, ?int $itemId = null ): bool { $sql = 'SELECT COUNT(*) FROM ' . $this->table . ' WHERE groupid = ? AND permission = ? AND itemid = ? AND granted = 1';
$stmt = $this->db->prepare($sql); $stmt->execute([$group->getId(), $permissionName, $itemId ?? 0]);
return $stmt->fetchColumn() > 0; }}3. ระดับการอนุญาต
หัวข้อที่มีชื่อว่า “3. ระดับการอนุญาต”<?php// Different permission levels with different scopes
class PermissionLevel{ // Module-level: Affects entire module public const LEVEL_MODULE = 'module';
// Admin-level: Admin panel access public const LEVEL_ADMIN = 'admin';
// Item-level: Specific objects/items public const LEVEL_ITEM = 'item';
// Field-level: Specific object fields public const LEVEL_FIELD = 'field';
// Action-level: Specific actions/operations public const LEVEL_ACTION = 'action';}4. สิทธิ์ระดับวัตถุ
หัวข้อที่มีชื่อว่า “4. สิทธิ์ระดับวัตถุ”<?php// Fine-grained control for specific items
class Item extends XoopsObject{ /** * Check if user can view this item */ public function canView(User $user): bool { // Public items anyone can view if ($this->getVar('status') === 'published') { return true; }
// Owner can always view their items if ($this->getVar('user_id') === $user->getId()) { return true; }
// Check group permissions $permChecker = xoops_getActiveModule()->getPermissionChecker(); return $permChecker->hasPermission( $user, 'item_view', $this->getVar('id') ); }
public function canEdit(User $user): bool { // Owner can edit their items if ($this->getVar('user_id') === $user->getId()) { return $permChecker->hasPermission($user, 'item_edit', $this->getVar('id')); }
// Check if user can edit all items return $permChecker->hasPermission($user, 'item_edit_all', $this->getVar('id')); }
public function canDelete(User $user): bool { return $permChecker->hasPermission($user, 'item_delete', $this->getVar('id')); }}5. การใช้งานในคอนโทรลเลอร์
หัวข้อที่มีชื่อว่า “5. การใช้งานในคอนโทรลเลอร์”<?php// Example: Article controller
class ArticleController{ private PermissionChecker $permChecker;
public function view(int $id, User $user): Response { $article = $this->repository->find($id);
// Check permission if (!$article->canView($user)) { throw new AccessDeniedException('Cannot view this article'); }
return new HtmlResponse($this->renderArticle($article)); }
public function edit(int $id, User $user): Response { $article = $this->repository->find($id);
// Check permission if (!$article->canEdit($user)) { throw new AccessDeniedException('Cannot edit this article'); }
// Handle form submission if ($this->request->isMethod('POST')) { $article->setVar('title', $this->request->getPost('title')); $article->setVar('content', $this->request->getPost('content')); $this->repository->insert($article);
$this->auditLog('ARTICLE_EDITED', ['id' => $id, 'user_id' => $user->getId()]);
// Invalidate permission cache $this->permChecker->clearCache($user->getId());
return new RedirectResponse('/article/' . $id); }
return new HtmlResponse($this->renderForm($article)); }
public function delete(int $id, User $user): Response { $article = $this->repository->find($id);
if (!$article->canDelete($user)) { throw new AccessDeniedException('Cannot delete this article'); }
$this->repository->delete($article);
$this->auditLog('ARTICLE_DELETED', ['id' => $id, 'user_id' => $user->getId()]);
// Invalidate cache $this->permChecker->clearCache($user->getId());
return new JsonResponse(['success' => true]); }}ผลที่ตามมา
หัวข้อที่มีชื่อว่า “ผลที่ตามมา”ผลเชิงบวก
หัวข้อที่มีชื่อว่า “ผลเชิงบวก”- การควบคุมแบบละเอียด - การจัดการสิทธิ์ที่ได้รับการปรับแต่งอย่างละเอียด
- ได้มาตรฐาน - สอดคล้องกันในทุกโมดูล
- แคช - ปรับปรุงประสิทธิภาพด้วยการแคช
- ตรวจสอบได้ - ติดตามว่าใครเปลี่ยนแปลงอะไร
- ยืดหยุ่น - รองรับการอนุญาตแบบกำหนดเอง
- ปรับขนาดได้ - จัดการลำดับชั้นการอนุญาตที่ซับซ้อน
- ทดสอบได้ - ทดสอบหน่วยได้ง่าย
ผลกระทบเชิงลบ
หัวข้อที่มีชื่อว่า “ผลกระทบเชิงลบ”- ความซับซ้อน - มีโค้ดให้จัดการมากขึ้น
- ค่าใช้จ่ายฐานข้อมูล - ตารางและการรวมเพิ่มเติม
- แคชใช้ไม่ได้ - ต้องล้างแคชเมื่อมีการเปลี่ยนแปลง
- Learning Curve - นักพัฒนาต้องเข้าใจระบบ
- ประสิทธิภาพ - หากแคชกำหนดค่าไม่ถูกต้อง
ความเสี่ยงและการบรรเทาผลกระทบ
หัวข้อที่มีชื่อว่า “ความเสี่ยงและการบรรเทาผลกระทบ”| ความเสี่ยง | ความรุนแรง | การบรรเทาผลกระทบ |
|---|---|---|
| สิทธิ์ที่ซับซ้อนมากเกินไป | ปานกลาง | ค่าเริ่มต้นที่ดี เอกสารประกอบ |
| แคชข้อมูลเก่า | สูง | TTL การทำให้เป็นโมฆะอย่างชาญฉลาด |
| การถดถอยประสิทธิภาพ | ปานกลาง | เกณฑ์มาตรฐาน เพิ่มประสิทธิภาพการสืบค้น |
| บายพาสการอนุญาต | สูง | การตรวจสอบความปลอดภัย การทดสอบ |
รูปแบบการออกแบบการอนุญาต
หัวข้อที่มีชื่อว่า “รูปแบบการออกแบบการอนุญาต”รูปแบบ 1: การอนุญาตตามเจ้าของ
หัวข้อที่มีชื่อว่า “รูปแบบ 1: การอนุญาตตามเจ้าของ”<?php// User can edit their own items but not others'
public function canEdit(User $user): bool{ // Owner can always edit if ($this->isOwner($user)) { return true; }
// Check group permissions for editing others' items return $this->permChecker->hasPermission($user, 'edit_all_items');}
private function isOwner(User $user): bool{ return $this->getVar('user_id') === $user->getId();}รูปแบบ 2: การอนุญาตตามสถานะ
หัวข้อที่มีชื่อว่า “รูปแบบ 2: การอนุญาตตามสถานะ”<?php// Different permissions based on status
public function canView(User $user): bool{ switch ($this->getVar('status')) { case 'published': // Anyone with module permission can view return $this->permChecker->hasPermission($user, 'item_view');
case 'draft': // Only owner or admin can view return $this->isOwner($user) || $this->permChecker->hasPermission($user, 'admin_manage');
case 'archived': // Only admin can view return $this->permChecker->hasPermission($user, 'admin_manage');
default: return false; }}รูปแบบ 3: การอนุญาตตามบทบาท
หัวข้อที่มีชื่อว่า “รูปแบบ 3: การอนุญาตตามบทบาท”<?php// Check against specific roles
public function hasAdminRole(User $user): bool{ return $user->getGroups()->contains('admin_group');}
public function hasModeratorRole(User $user): bool{ return $user->getGroups()->contains('moderator_group') || $this->hasAdminRole($user);}
public function canModerate(User $user): bool{ return $this->hasModeratorRole($user);}การตัดสินใจที่เกี่ยวข้อง
หัวข้อที่มีชื่อว่า “การตัดสินใจที่เกี่ยวข้อง”- ADR-001: สถาปัตยกรรมโมดูลาร์ - โมดูลกำหนดสิทธิ์
- ADR-004: ระบบรักษาความปลอดภัย - รากฐานเพื่อความปลอดภัย
- ADR-005: มิดเดิลแวร์ - สามารถบังคับใช้สิทธิ์ได้
อ้างอิง
หัวข้อที่มีชื่อว่า “อ้างอิง”โมเดลการอนุญาต
หัวข้อที่มีชื่อว่า “โมเดลการอนุญาต”- RBAC (การควบคุมการเข้าถึงตามบทบาท)
- ABAC (การควบคุมการเข้าถึงตามคุณลักษณะ)
- ACL (รายการควบคุมการเข้าถึง)
การนำไปปฏิบัติ
หัวข้อที่มีชื่อว่า “การนำไปปฏิบัติ”รายการตรวจสอบการดำเนินการ
หัวข้อที่มีชื่อว่า “รายการตรวจสอบการดำเนินการ”- กำหนดระดับการอนุญาตมาตรฐาน
- สร้างคลาส PermissionChecker
- ใช้กลยุทธ์การแคช
- เพิ่มการบันทึกการตรวจสอบ
- สร้างฟังก์ชันตัวช่วย
- เขียนแบบทดสอบที่ครอบคลุม
- เอกสารสำหรับนักพัฒนา
- อัปเดตโมดูลทั้งหมด
- การเพิ่มประสิทธิภาพการทำงาน
- การตรวจสอบความปลอดภัย
ประวัติเวอร์ชัน
หัวข้อที่มีชื่อว่า “ประวัติเวอร์ชัน”| เวอร์ชั่น | วันที่ | การเปลี่ยนแปลง |
|---|---|---|
| 1.0.0 | 2024-01-28 | เอกสารเริ่มต้น |
#xoops #adr #permissions #authorization #rbac #security