title: “RBAC & User Management” description: “Role-Based Access Control: RoleManager 1398 baris, 13 role templates, 38 permissions, 3 SoD rules, ERPAccessGuard, MenuAccessProfile, dan real-time sync.”
RBAC & User Management

useCompanyRole.jsx hook (524 baris) dengan aggressive caching (60-second TTL), deduplication of in-flight fetches, dan real-time cache invalidation via BroadcastChannel.
Sistem RBAC Quinn of Spicy dibangun di atas lima entitas inti yang saling terhubung: User, Company, CompanyMember, CompanyInvitation, dan MenuAccessProfile. Kelima entitas ini membentuk fondasi kontrol akses multi-tenant yang memastikan setiap pengguna hanya dapat mengakses fitur, menu, dan data sesuai dengan peran dan izin yang diberikan.
Arsitektur Komponen
Ringkasan Alur Kontrol Akses
Sistem RBAC bekerja dalam tiga lapisan utama:- Lapisan Autentikasi — User login dan sistem memverifikasi identitas melalui entity
User. Setiap user memilikiadmin_typedanadmin_tieryang menentukan hak akses di level platform. - Lapisan Keanggotaan Company — Entity
CompanyMembermenghubungkan user ke company tertentu dengan role dan permissions. Satu user bisa menjadi member di beberapa company sekaligus. - Lapisan Akses Menu — Entity
MenuAccessProfilememetakan role ke daftar menu yang boleh ditampilkan, sehingga sidebar navigasi otomatis menyesuaikan dengan hak akses pengguna.
Entity Relationship Diagram
Entity Schema Tables
User
EntitasUser merepresentasikan akun pengguna platform. Setiap pengguna memiliki identitas unik, preferensi subscription, dan hak akses administratif di level platform (berbeda dengan hak akses di level company).
Company
EntitasCompany merepresentasikan perusahaan atau organisasi yang menggunakan sistem ERP. Setiap company memiliki owner, konfigurasi modul aktif, dan pengaturan operasional.
CompanyMember
EntitasCompanyMember adalah jantung dari sistem RBAC — menghubungkan user ke company dengan role dan 38 permission flags yang sangat granular.
CompanyInvitation
EntitasCompanyInvitation merepresentasikan undangan keanggotaan yang dikirimkan kepada user yang belum bergabung. Invitation memiliki lifecycle status yang jelas dan akan expired setelah waktu yang ditentukan.
MenuAccessProfile
EntitasMenuAccessProfile mendefinisikan profil akses menu per role — menentukan menu/sidebar mana saja yang boleh ditampilkan untuk setiap role dalam suatu company.
13 Role Templates
Sistem RBAC Quinn of Spicy mendukung 13 role templates yang dirancang untuk mencakup berbagai fungsi operasional dalam perusahaan ERP. Setiap role memiliki set permission default yang dapat dikustomisasi lebih lanjut.38 Permission Flags — Matriks Lengkap
Berikut adalah seluruh 38 permission flags yang tersedia dalamCompanyMember.permissions dan CompanyInvitation.permissions. Setiap flag bertipe boolean dan dapat diaktifkan/nonaktifkan secara independen.
Dashboard & Tugas
Catatan (Notes)
HR & Payroll
Keuangan (Finance)
Inventaris (Inventory)
Proyek (Projects)
POS / Kasir
Laporan (Reports)
Manajemen User & Settings
Produksi (Manufacturing)
Distribusi & Sales Channel
B2B & Invoice
Enum Reference Tables
CompanyMember.role
CompanyInvitation.role
CompanyMember.status
CompanyInvitation.status
User.role
User.admin_type
Catatan Penting:admin_typeadalah hak akses di level platform/aplikasi, bukan di level company. Company owner ditentukan oleh fieldCompany.owner_id.
User.admin_tier
User.subscription_plan
User.membership_duration_type
Company.industry
MenuAccessProfile.role
MenuAccessProfile.dashboard_type
Role Assignment Lifecycle — State Diagram
Sequence Diagrams — Alur Utama
1. Member Invitation Flow
2. Permission Check Flow
3. Menu Access Filtering Flow
4. Role Assignment Flow
Segregation of Duties (SoD)
3 aturan kritis untuk mencegah fraud dan conflict of interest:
SoD Validation Matrix:
Validasi SoD di Level Server
Validasi SoD dilakukan di dua lapisan:- Client-side (RoleManager.jsx) — Memberikan warning visual saat admin mengatur permissions yang bertentangan. Admin harus konfirmasi eksplisit untuk melanjutkan.
- Server-side (Server Function) — Menolak request yang melanggar aturan SoD dengan error message yang jelas. Ini adalah lapisan pertahanan terakhir yang tidak bisa di-bypass dari client.
Fitur Utama
1. Member Invitation Flow
Proses invitation menggunakan idempotency key untuk mencegah duplikasi:2. Permission Resolution
useCompanyRole.jsx hook menggunakan aggressive caching untuk performa:
Resolution Flow:
3. Owner Role Protection
Hanya original company owner yang bisa assign roleowner:
Check: selectedCompany.owner_email === currentUser.email
4. ERPAccessGuard
ERPAccessGuard.jsx (569 baris) melindungi company-specific pages:
Features:
Grace Period:
5. Multi-Role Support
Satu user bisa memiliki lebih dari satu role di company yang berbeda: Permission Merging:
Example:
6. Audit Trail
Setiap perubahan user/role dicatat di audit log:
Audit Log Detail:
Cara Akses
Menu: Admin > User Management atau Settings > Company Settings > Members & RolesFlow Penggunaan
Admin / Owner
- Buka User Management dari sidebar
- Klik “Invite Member” untuk invite user baru
- Enter email dan pilih role dari 13 role templates
- Customize permissions dari matrix 38 flag
- Send invitation — sistem otomatis cek apakah user sudah terdaftar
- Monitor invitation status (pending/accepted/rejected/expired)
- Untuk existing members: edit role dan permissions sesuai kebutuhan
- Review audit trail untuk security monitoring
- Pastikan SoD rules tidak dilanggar saat assign permissions
Member
- Terima invitation email
- Click accept link
- Login atau register jika belum punya akun
- Auto-joined ke company dengan role yang di-assign
- Akses fitur sesuai permissions yang diberikan
- Sidebar navigasi otomatis ter-filter sesuai MenuAccessProfile
Integrasi Cross-Module
Hubungan dengan Modul Lain
Row-Level Security (RLS)
EntitasCompanyMember dan CompanyInvitation dilindungi oleh Row-Level Security policies yang memastikan setiap user hanya bisa mengakses data yang relevan:
Kondisi Akses CompanyMember
Sebuah recordCompanyMember dapat dibaca/ditulis jika salah satu kondisi berikut terpenuhi:
- Active company match:
data.company_id === user.active_company_iddancompany_idtidak null/kosong - Creator:
created_by_id === user.id— user yang membuat record - Self-access:
data.user_email === user.emailataudata.user_id === user.id— data milik sendiri - Platform admin:
user.role === 'admin'— administrator platform
Kondisi Akses CompanyInvitation
Sebuah recordCompanyInvitation dapat dibaca/ditulis jika salah satu kondisi berikut terpenuhi:
- Active company match:
data.company_id === user.active_company_iddancompany_idtidak null/kosong - Creator:
created_by_id === user.id— user yang mengirim undangan - Invitee:
data.invited_email === user.email— user yang diundang - Platform admin:
user.role === 'admin'— administrator platform
Security Best Practices
1. Principle of Least Privilege
Beri akses minimal yang dibutuhkan untuk pekerjaan. Jangan beri Admin role kalau cuma butuh Kasir.2. Regular Review
Review user roles setiap bulan:- Hapus user yang sudah resign
- Adjust role jika ada perubahan tanggung jawab
- Cek audit log untuk aktivitas mencurigakan
- Pastikan
assigned_locationsmasih relevan
3. SoD Enforcement
Selalu enforce Segregation of Duties:- Stock opname: counter ≠ approver
- Manufacturing: operator ≠ QC
- Finance: CS ≠ cash verifier
4. Owner Protection
Hanya transfer ownership setelah pertimbangan matang — original owner punya kontrol penuh atas company.5. Location-Based Access
Gunakanassigned_locations untuk membatasi akses gudang/outlet per member. Ini penting untuk perusahaan multi-cabang yang ingin memastikan setiap staff hanya mengakses lokasi yang menjadi tanggung jawabnya.
6. Invitation Hygiene
- Set
expires_atyang wajar (rekomendasi: 7 hari) - Cancel undangan yang tidak direspon dalam waktu lama
- Jangan share invitation link di channel yang tidak aman
- Verifikasi email invitee sebelum mengirim undangan
Tips
- 13 role templates mencakup sebagian besar use case — buat custom role hanya jika benar-benar butuh
- SoD rules adalah anti-fraud control — jangan bypass kecuali ada alasan kuat dan compensating control
- BroadcastChannel sync memastikan permission changes propagate instantly ke semua tabs
- Grace period 3 hari memberi waktu untuk renew membership sebelum user terblokir total
- Audit trail bersifat append-only — tidak bisa dihapus, memastikan forensic integrity
- Permission caching (60s TTL) balancing antara performa dan freshness — adjust jika perlu
- Gunakan
MenuAccessProfileuntuk mengontrol visibility sidebar per role — lebih fleksibel daripada hardcode - Field
assigned_locationspada CompanyMember mendukung RBAC berbasis lokasi — ideal untuk bisnis multi-cabang working_hourspada CompanyMember dapat digunakan untuk time-based access control di masa depandashboard_typepada MenuAccessProfile memungkinkan setiap role melihat dashboard yang berbeda dan relevan dengan fungsinya
