10 KiB
10 KiB
📋 Plan: Menu & Action Access Control System
🎯 Tujuan
Membangun sistem akses kontrol yang memungkinkan:
- 1 Menu memiliki banyak Actions - Satu menu dapat memiliki berbagai action (view table, create, edit, delete, approve, export, dll)
- User Level dapat di-assign Menu - Setiap user level dapat di-assign menu apa saja yang bisa diakses
- User Level dapat di-assign Actions per Menu - Setiap user level dapat di-assign action apa saja yang bisa dilakukan di setiap menu (contoh: Creator hanya bisa create dan edit, Approver bisa delete)
🔍 Analisis Kebutuhan
Use Case 1: Menu "Content Management"
- Actions yang tersedia:
view- Melihat daftar contentcreate- Membuat content baruedit- Mengedit content yang adadelete- Menghapus contentapprove- Approve contentexport- Export data content
Use Case 2: User Level "Creator"
- Menu yang bisa diakses: Content Management
- Actions yang bisa dilakukan:
- ✅
view- Bisa melihat daftar - ✅
create- Bisa membuat baru - ✅
edit- Bisa mengedit - ❌
delete- Tidak bisa menghapus - ❌
approve- Tidak bisa approve - ❌
export- Tidak bisa export
- ✅
Use Case 3: User Level "Approver"
- Menu yang bisa diakses: Content Management
- Actions yang bisa dilakukan:
- ✅
view- Bisa melihat daftar - ❌
create- Tidak bisa membuat baru - ❌
edit- Tidak bisa mengedit - ✅
delete- Bisa menghapus - ✅
approve- Bisa approve - ✅
export- Bisa export
- ✅
🏗️ Arsitektur Sistem
Opsi 1: Menu-Action Based (Recommended) ⭐
Konsep:
- Menu memiliki Actions langsung (bukan melalui Module)
- User Level memiliki akses ke Menu
- User Level memiliki akses ke Actions di dalam Menu
Struktur Database:
1. master_menus (Existing - Enhanced)
-- Sudah ada, tidak perlu perubahan
-- Menu seperti: "Content Management", "User Management", "Settings"
2. menu_actions (New)
CREATE TABLE menu_actions (
id SERIAL PRIMARY KEY,
menu_id INT NOT NULL,
action_code VARCHAR(50) NOT NULL, -- 'view', 'create', 'edit', 'delete', 'approve', 'export'
action_name VARCHAR(255) NOT NULL, -- 'View Content', 'Create Content', etc.
description TEXT NULL,
path_url VARCHAR(255) NULL, -- Optional: untuk routing frontend
http_method VARCHAR(10) NULL, -- Optional: 'GET', 'POST', 'PUT', 'DELETE'
position INT NULL,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
FOREIGN KEY (menu_id) REFERENCES master_menus(id) ON DELETE CASCADE,
UNIQUE(menu_id, action_code)
);
CREATE INDEX idx_menu_actions_menu_id ON menu_actions(menu_id);
CREATE INDEX idx_menu_actions_action_code ON menu_actions(action_code);
3. user_level_menu_accesses (New)
CREATE TABLE user_level_menu_accesses (
id SERIAL PRIMARY KEY,
user_level_id INT NOT NULL,
menu_id INT NOT NULL,
can_access BOOLEAN DEFAULT TRUE,
client_id UUID NULL,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
FOREIGN KEY (user_level_id) REFERENCES user_levels(id) ON DELETE CASCADE,
FOREIGN KEY (menu_id) REFERENCES master_menus(id) ON DELETE CASCADE,
UNIQUE(user_level_id, menu_id, client_id)
);
CREATE INDEX idx_user_level_menu_accesses_user_level_id ON user_level_menu_accesses(user_level_id);
CREATE INDEX idx_user_level_menu_accesses_menu_id ON user_level_menu_accesses(menu_id);
4. user_level_menu_action_accesses (New)
CREATE TABLE user_level_menu_action_accesses (
id SERIAL PRIMARY KEY,
user_level_id INT NOT NULL,
menu_id INT NOT NULL,
action_code VARCHAR(50) NOT NULL,
can_access BOOLEAN DEFAULT TRUE,
client_id UUID NULL,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
FOREIGN KEY (user_level_id) REFERENCES user_levels(id) ON DELETE CASCADE,
FOREIGN KEY (menu_id) REFERENCES master_menus(id) ON DELETE CASCADE,
FOREIGN KEY (menu_id, action_code) REFERENCES menu_actions(menu_id, action_code) ON DELETE CASCADE,
UNIQUE(user_level_id, menu_id, action_code, client_id)
);
CREATE INDEX idx_user_level_menu_action_accesses_user_level_id ON user_level_menu_action_accesses(user_level_id);
CREATE INDEX idx_user_level_menu_action_accesses_menu_id ON user_level_menu_action_accesses(menu_id);
CREATE INDEX idx_user_level_menu_action_accesses_action_code ON user_level_menu_action_accesses(action_code);
Relasi:
master_menus (1) ─────< (N) menu_actions
│ │
│ │
│ (1) │ (N)
│ │
∨ ∨
user_level_menu_accesses user_level_menu_action_accesses
│ │
│ (N) │ (N)
│ │
∨ ∨
user_levels (1) ──────────────┘
Keuntungan:
- ✅ Lebih sederhana dan intuitif
- ✅ Langsung ke point: Menu → Actions
- ✅ Mudah di-manage: assign menu, lalu assign actions
- ✅ Tidak perlu konsep "Module" yang membingungkan
- ✅ Frontend lebih mudah: cek menu access, lalu cek action access
Kekurangan:
- ❌ Perlu migration dari sistem Module yang ada
- ❌ Perlu refactor middleware dan service yang sudah ada
Opsi 2: Keep Module, Enhance Structure
Konsep:
- Tetap menggunakan Module, tapi Module sekarang lebih spesifik ke Menu
- Module = Action di dalam Menu
- User Level memiliki akses ke Menu
- User Level memiliki akses ke Module (Action) di dalam Menu
Struktur Database:
1. master_menus (Existing)
-- Tidak berubah
2. master_modules (Existing - Enhanced)
-- Tetap ada, tapi sekarang lebih spesifik:
-- Module sekarang = Action di dalam Menu
-- action_type menjadi lebih penting
3. menu_modules (Existing - Enhanced)
-- Tetap ada, relasi Menu dengan Module (Action)
-- Tapi sekarang lebih strict: 1 module hanya untuk 1 menu
4. user_level_menu_accesses (New)
-- Sama seperti Opsi 1
5. user_level_module_accesses (Existing)
-- Tetap ada, tapi sekarang lebih spesifik:
-- Module = Action di dalam Menu
Keuntungan:
- ✅ Tidak perlu migration besar-besaran
- ✅ Bisa reuse struktur yang sudah ada
- ✅ Lebih fleksibel (module bisa digunakan oleh banyak menu)
Kekurangan:
- ❌ Konsep "Module" masih membingungkan
- ❌ Lebih kompleks: Menu → Module → Action
- ❌ Perlu mapping yang lebih kompleks
🎯 Rekomendasi: Opsi 1 (Menu-Action Based)
Alasan:
- Lebih intuitif - Langsung ke point: Menu punya Actions
- Lebih mudah di-manage - Admin langsung assign menu dan actions
- Lebih mudah di-frontend - Cek menu access, lalu cek action access
- Lebih scalable - Mudah ditambah menu baru dengan actions baru
- Lebih maintainable - Struktur lebih jelas dan mudah dipahami
📝 Implementation Plan
Phase 1: Database Schema
- ✅ Buat tabel
menu_actions - ✅ Buat tabel
user_level_menu_accesses - ✅ Buat tabel
user_level_menu_action_accesses - ✅ Buat migration script
- ✅ Migrate data dari
master_modulesdanmenu_moduleskemenu_actions(jika perlu)
Phase 2: Backend Entities & Repositories
- ✅ Buat entity
MenuActions - ✅ Buat entity
UserLevelMenuAccesses - ✅ Buat entity
UserLevelMenuActionAccesses - ✅ Buat repository untuk masing-masing entity
- ✅ Buat service untuk masing-masing entity
Phase 3: Backend API Endpoints
- ✅ CRUD API untuk
menu_actions - ✅ CRUD API untuk
user_level_menu_accesses - ✅ CRUD API untuk
user_level_menu_action_accesses - ✅ API untuk get menu actions by menu_id
- ✅ API untuk get user level menu accesses
- ✅ API untuk get user level menu action accesses
Phase 4: Backend Middleware
- ✅ Buat middleware
CheckMenuAccess- cek apakah user level bisa akses menu - ✅ Buat middleware
CheckMenuActionAccess- cek apakah user level bisa akses action di menu - ✅ Update existing middleware untuk menggunakan struktur baru
Phase 5: Frontend Services
- ✅ Buat service untuk
menu_actions - ✅ Buat service untuk
user_level_menu_accesses - ✅ Buat service untuk
user_level_menu_action_accesses - ✅ Update existing services
Phase 6: Frontend UI - Menu Management
- ✅ Update halaman Menu Management untuk menampilkan Actions
- ✅ Tambah form untuk manage Actions di setiap Menu
- ✅ Tambah UI untuk assign Actions ke Menu
Phase 7: Frontend UI - User Level Management
- ✅ Update halaman User Level Management
- ✅ Tambah tab "Menu Access" untuk assign menu ke user level
- ✅ Tambah tab "Action Access" untuk assign actions per menu ke user level
- ✅ Update form User Level untuk include menu dan action access
Phase 8: Frontend UI - Permission Check
- ✅ Buat hook
useMenuAccessuntuk cek menu access - ✅ Buat hook
useMenuActionAccessuntuk cek action access - ✅ Update components untuk menggunakan hooks
- ✅ Hide/show UI elements berdasarkan permission
Phase 9: Testing & Documentation
- ✅ Test semua API endpoints
- ✅ Test middleware
- ✅ Test frontend UI
- ✅ Update documentation
🔄 Migration Strategy
Option A: Clean Slate (Recommended)
- Buat struktur baru dari awal
- Data lama tetap ada tapi tidak digunakan
- Migrate data secara bertahap jika perlu
Option B: Gradual Migration
- Keep struktur lama dan baru berjalan bersamaan
- Migrate data dari lama ke baru
- Deprecate struktur lama setelah semua ter-migrate
📊 Comparison: Current vs Proposed
Current System
Menu → Module (via menu_modules) → User Level Access (via user_level_module_accesses)
- Module adalah entitas terpisah
- Module bisa digunakan oleh banyak menu
- Akses diberikan ke Module, bukan ke Menu + Action
Proposed System
Menu → Actions (via menu_actions) → User Level Menu Access → User Level Action Access
- Actions langsung di dalam Menu
- Actions spesifik untuk Menu tertentu
- Akses diberikan ke Menu dan Actions secara terpisah
✅ Next Steps
- Review & Approval - Review plan ini dengan tim
- Decision - Pilih antara Opsi 1 atau Opsi 2
- Database Design - Finalize database schema
- Implementation - Mulai implementasi sesuai phase yang sudah direncanakan
📚 Reference
- Current system:
docs/MENU_MODULE_ACCESS_SYSTEM.md - Implementation summary:
docs/IMPLEMENTATION_SUMMARY_MENU_MODULE_ACCESS.md