RBAC
Role definitions, permission verbs, row-level filters, and role profiles in P9.
Access Control
P9 RBAC provides granular access control at the object, field, and row level. Roles are defined in .rbac files and profiles in .profiles.rbac files.
Role Structure
@company "{company}"
role RoleName {
allow ObjectName
allow ApplicationName
allow ObjectName {
view
create
update
patch
}
report "report-name"
report *
}
Company Declaration
Every RBAC file starts with a company declaration:
@company "{company}" // Dynamic company placeholder
@company "CompanyName" // Specific company
Permission Types
| Permission | Description |
|---|---|
view |
View/read records |
create |
Create new records |
update |
Update existing records |
patch |
Partial update |
delete |
Delete records |
list or List |
List view access |
Permission Syntaxes
Full Access to Object:
Grants all permissions (view, create, update, patch, delete, list):
role Manager {
allow Contract
allow Payment
allow Building
}
Application-Level Access:
Grant all permissions to all objects in an application:
role Admin {
allow Finance
allow Leasing
allow FacilityManagement
}
Specific Permissions:
role Viewer {
allow Contract {
view
list
}
allow Building {
view
}
}
Permissions with Filters:
Restrict access based on conditions:
role RegionalManager {
allow Contract {
view {
filter: " Region = '{User.Region}' "
}
create
update
patch
}
allow Building {
view {
filter: " Region = '{User.Region}' "
}
}
}
Filter Patterns
| Pattern | Description | Example |
|---|---|---|
{User.RecordId} |
Current user's record ID | filter: " Team = '{User.RecordId}' " |
{User.xId} |
Current user's external ID | filter: " CreatedById = '{User.xId}' " |
{User.Department} |
User's department | filter: " Department = '{User.Department}' " |
{User.Building.Id} |
Related field value | filter: " Building = '{User.Building.Id}' " |
Report Permissions
role Manager {
report * // All reports
report "blanket-agreement" // Specific report
report "purchase-order"
}
Global Role (Wildcard)
Apply rules to all roles using role *:
role * {
deny * {
delete
}
}
This denies delete permission globally across all roles.
Deny Permissions
Explicitly deny permissions:
role * {
deny * {
delete
}
}
role RestrictedRole {
deny ObjectName {
delete
update
}
}
Complete RBAC Examples
Example 1: Tenant Role (External User)
@company "{company}"
role Tenant {
allow Activity
allow ServiceRequest
allow Tenant
allow WorkOrderJob
allow WorkOrder
allow MoveOutRequest
allow FitOutRequest
}
Example 2: Technician Role (Filtered Access)
@company "{company}"
role Technician {
allow Activity
allow ServiceRequest
allow WorkOrder
allow EmergencyJob {
view {
filter: " Team = '{User.RecordId}' "
}
create
update
patch
}
allow WorkOrderJob {
view {
filter: " Team = '{User.RecordId}' "
}
update
patch
}
allow PettyCashRequest {
view {
filter: " CreatedById = '{User.xId}' "
}
create
update
patch
list
}
allow Employee {
view
}
allow Company {
List
}
allow Currency {
List
}
}
Example 3: Finance Manager Role
@company "{company}"
role Finance_Manager {
allow Finance
allow Supplier {
view
}
allow Payment
allow BankAccount
allow PurchaseOrder
allow PurchaseInvoice
allow Company {
List
}
report *
}
Example 4: Supervisor Role
@company "{company}"
role Supervisor {
allow ServiceRequest
allow WorkOrder
allow WorkOrderJob
allow VisualInspection
allow MoveOutRequest
allow PettyCashRequest
allow PettyCash
allow Employee {
view
}
allow Building {
view
}
allow Unit {
view
}
allow Company {
List
}
}
Example 5: Supplier Role (External Portal)
@company "{company}"
role Supplier {
allow RequestForQuotation {
view
}
allow Quotation
allow Company {
List
}
allow TaxRule {
List
}
allow Currency {
List
}
}
Example 6: Global Restrictions with Admin
@company "{company}"
role * {
deny * {
delete
}
}
role Admin {
allow Finance
allow Leasing
allow FacilityManagement
report *
}
Role Profiles
Profiles combine multiple roles into reusable groups. Define profiles in .profiles.rbac files:
profile AccountantPayable {
include Accountant_Payable
include Petty_Cash_Approver
}
profile PayableController {
include Payable_Controller
include Purchase_Invoice_Approver
}
profile LeasingExecutive {
include Leasing_Executive
include Sales_Team
include Contract_Officer
}
profile PropertyManager {
include Leasing_Executive
include Finance_Viewer
include FM_Supervisor
}
Common Permission Patterns
Read-Only Access:
allow ObjectName {
view
}
Create and Edit (No Delete):
allow ObjectName {
view
create
update
patch
list
}
Full Access:
allow ObjectName
User's Own Records Only:
allow ObjectName {
view {
filter: " CreatedById = '{User.xId}' "
}
create
update
patch
list
}
Team-Based Access:
allow ObjectName {
view {
filter: " Team = '{User.RecordId}' "
}
create
update
patch
}
Department-Based Access:
allow ObjectName {
view {
filter: " Department = '{User.Department}' "
}
update
patch
}
Best Practices
- Use role * for global policies — Apply universal restrictions like delete denial
- Filter by user context — Use
{User.RecordId}and{User.xId}for user-specific filtering - Grant minimal permissions — Only provide necessary permissions
- Use application-level access sparingly — Prefer specific object permissions
- Combine with profiles — Use profiles to create reusable role combinations
- List permissions for lookups — Include
Listpermission for objects used in dropdowns - Include system objects — Grant access to Company, Currency, etc. for proper functionality
- Filter sensitive data — Restrict access to user's own records or team
- Document role purposes — Use clear role names that indicate responsibility
- Test permission combinations — Verify that role combinations don't create security gaps