# 📋 Plan: Menu & Action Access Control System ## 🎯 Tujuan Membangun sistem akses kontrol yang memungkinkan: 1. **1 Menu memiliki banyak Actions** - Satu menu dapat memiliki berbagai action (view table, create, edit, delete, approve, export, dll) 2. **User Level dapat di-assign Menu** - Setiap user level dapat di-assign menu apa saja yang bisa diakses 3. **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 content - `create` - Membuat content baru - `edit` - Mengedit content yang ada - `delete` - Menghapus content - `approve` - Approve content - `export` - 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) ```sql -- Sudah ada, tidak perlu perubahan -- Menu seperti: "Content Management", "User Management", "Settings" ``` #### 2. `menu_actions` (New) ```sql 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) ```sql 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) ```sql 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) ```sql -- Tidak berubah ``` #### 2. `master_modules` (Existing - Enhanced) ```sql -- Tetap ada, tapi sekarang lebih spesifik: -- Module sekarang = Action di dalam Menu -- action_type menjadi lebih penting ``` #### 3. `menu_modules` (Existing - Enhanced) ```sql -- Tetap ada, relasi Menu dengan Module (Action) -- Tapi sekarang lebih strict: 1 module hanya untuk 1 menu ``` #### 4. `user_level_menu_accesses` (New) ```sql -- Sama seperti Opsi 1 ``` #### 5. `user_level_module_accesses` (Existing) ```sql -- 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:** 1. **Lebih intuitif** - Langsung ke point: Menu punya Actions 2. **Lebih mudah di-manage** - Admin langsung assign menu dan actions 3. **Lebih mudah di-frontend** - Cek menu access, lalu cek action access 4. **Lebih scalable** - Mudah ditambah menu baru dengan actions baru 5. **Lebih maintainable** - Struktur lebih jelas dan mudah dipahami ## 📝 Implementation Plan ### Phase 1: Database Schema 1. ✅ Buat tabel `menu_actions` 2. ✅ Buat tabel `user_level_menu_accesses` 3. ✅ Buat tabel `user_level_menu_action_accesses` 4. ✅ Buat migration script 5. ✅ Migrate data dari `master_modules` dan `menu_modules` ke `menu_actions` (jika perlu) ### Phase 2: Backend Entities & Repositories 1. ✅ Buat entity `MenuActions` 2. ✅ Buat entity `UserLevelMenuAccesses` 3. ✅ Buat entity `UserLevelMenuActionAccesses` 4. ✅ Buat repository untuk masing-masing entity 5. ✅ Buat service untuk masing-masing entity ### Phase 3: Backend API Endpoints 1. ✅ CRUD API untuk `menu_actions` 2. ✅ CRUD API untuk `user_level_menu_accesses` 3. ✅ CRUD API untuk `user_level_menu_action_accesses` 4. ✅ API untuk get menu actions by menu_id 5. ✅ API untuk get user level menu accesses 6. ✅ API untuk get user level menu action accesses ### Phase 4: Backend Middleware 1. ✅ Buat middleware `CheckMenuAccess` - cek apakah user level bisa akses menu 2. ✅ Buat middleware `CheckMenuActionAccess` - cek apakah user level bisa akses action di menu 3. ✅ Update existing middleware untuk menggunakan struktur baru ### Phase 5: Frontend Services 1. ✅ Buat service untuk `menu_actions` 2. ✅ Buat service untuk `user_level_menu_accesses` 3. ✅ Buat service untuk `user_level_menu_action_accesses` 4. ✅ Update existing services ### Phase 6: Frontend UI - Menu Management 1. ✅ Update halaman Menu Management untuk menampilkan Actions 2. ✅ Tambah form untuk manage Actions di setiap Menu 3. ✅ Tambah UI untuk assign Actions ke Menu ### Phase 7: Frontend UI - User Level Management 1. ✅ Update halaman User Level Management 2. ✅ Tambah tab "Menu Access" untuk assign menu ke user level 3. ✅ Tambah tab "Action Access" untuk assign actions per menu ke user level 4. ✅ Update form User Level untuk include menu dan action access ### Phase 8: Frontend UI - Permission Check 1. ✅ Buat hook `useMenuAccess` untuk cek menu access 2. ✅ Buat hook `useMenuActionAccess` untuk cek action access 3. ✅ Update components untuk menggunakan hooks 4. ✅ Hide/show UI elements berdasarkan permission ### Phase 9: Testing & Documentation 1. ✅ Test semua API endpoints 2. ✅ Test middleware 3. ✅ Test frontend UI 4. ✅ 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 1. **Review & Approval** - Review plan ini dengan tim 2. **Decision** - Pilih antara Opsi 1 atau Opsi 2 3. **Database Design** - Finalize database schema 4. **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`