Skip to main content

Role Permissions

The Role Permissions system provides admin-configurable control over which user roles can perform specific actions in the application.

info

Unlike Module Permissions (which control item creation within modules), Role Permissions control broader application actions like creating bids, accessing admin panel, and managing users.

Permission Types

Bid Management Permissions

Control who can perform bid-level operations:

PermissionDescriptionDefault Roles
create_bidCreate new bidsADMIN, ESTIMATOR
edit_bidEdit existing bids and scopesADMIN, ESTIMATOR
delete_bidDelete bids permanentlyADMIN
view_all_bidsView bids created by other usersAll roles
duplicate_bidCreate copies of existing bidsADMIN, ESTIMATOR
share_bidGenerate share codes for bidsADMIN, ESTIMATOR
change_bid_statusChange bid status (submit, award, mark lost)ADMIN, ESTIMATOR

Administration Permissions

Control admin panel access:

PermissionDescriptionDefault Roles
access_admin_panelAccess the admin panelADMIN
manage_usersCreate, edit, and disable usersADMIN
view_audit_logView system audit logsADMIN

Pricing & Rates Permissions

Control pricing database access:

PermissionDescriptionDefault Roles
manage_pricingEdit pricing database and ratesADMIN
view_pricingView pricing database (read-only)ADMIN, ESTIMATOR, PM, OPS, ACCOUNTING

Admin Configuration

1
Navigate to Role Permissions

Go to Admin Panel → Settings → Role Permissions

2
View Permission Matrix

The matrix interface shows:

  • Rows: Permission names with descriptions
  • Columns: User roles (ADMIN, ESTIMATOR, PM, etc.)
  • Cells: Checkboxes for enabled/disabled state
3
Enable/Disable Permissions

Click checkboxes to grant or revoke permissions for specific roles.

Changes take effect immediately (no save button required).

4
Reset to Defaults (Optional)

Click "Reset to Defaults" to restore all permissions to their default configuration.

warning

This will overwrite all custom permission changes.

Permission Matrix UI

The admin interface organizes permissions by category:

┌─────────────────────────────────────────────────────┐
│ Bid Management │
├─────────────────┬──────┬──────────┬────┬─────┬─────┤
│ Permission │ADMIN │ESTIMATOR │ PM │ OPS │ACCT │
├─────────────────┼──────┼──────────┼────┼─────┼─────┤
│ Create Bid │ ✓ │ ✓ │ │ │ │
│ Edit Bid │ ✓ │ ✓ │ │ │ │
│ Delete Bid │ ✓ │ │ │ │ │
└─────────────────┴──────┴──────────┴────┴─────┴─────┘
tip

Color-Coded Actions: Permission names use badges to show status (active/inactive).

Using Permissions in Code

Frontend Components

Check permissions before rendering UI elements:

import { useCanPerform } from '../context/RolePermissionsContext';

function BidActions({ bid }) {
const canEdit = useCanPerform('edit_bid');
const canDelete = useCanPerform('delete_bid');
const canShare = useCanPerform('share_bid');

return (
<div>
{canEdit && <Button onClick={handleEdit}>Edit</Button>}
{canShare && <Button onClick={handleShare}>Share</Button>}
{canDelete && <Button onClick={handleDelete}>Delete</Button>}
</div>
);
}

Multiple Permission Checks

Use the context for complex authorization logic:

import { useRolePermissions } from '../context/RolePermissionsContext';

function AdminDashboard() {
const { canPerform, loading } = useRolePermissions();

if (loading) return <Spinner />;

const canAccessAdmin = canPerform('access_admin_panel');
const canManageUsers = canPerform('manage_users');
const canViewAudit = canPerform('view_audit_log');

if (!canAccessAdmin) {
return <AccessDenied />;
}

return (
<Dashboard>
{canManageUsers && <UsersSection />}
{canViewAudit && <AuditLogSection />}
</Dashboard>
);
}

API Endpoints

MethodEndpointDescriptionAuth
GET/api/role-permissionsGet all permissionsAuthenticated
GET/api/role-permissions/:keyGet single permissionAuthenticated
GET/api/role-permissions/check/:keyCheck if user can perform actionAuthenticated
PUT/api/role-permissions/:keyUpdate permission rolesAdmin only
POST/api/role-permissions/resetReset all to defaultsAdmin only

Default Behavior

Auto-Seeding

If permissions haven't been configured, default permissions are automatically created on first access.

API Failure Fallback

If the API fails, the frontend falls back to hardcoded defaults to ensure the application remains usable.

ADMIN Always Has Access

The ADMIN role cannot be removed from any permission via the UI. ADMIN always has full access.

Permission Categories

Permissions are grouped into logical categories for easier management:

CategoryPermissions
Bidscreate_bid, edit_bid, delete_bid, duplicate_bid, share_bid, change_bid_status, view_all_bids
Adminaccess_admin_panel, manage_users, view_audit_log
Pricingmanage_pricing, view_pricing
tip

Future versions may support custom categories and permission groups.

Migration from Hardcoded Permissions

Before (Hardcoded)

const { role } = useRole();
const canEdit = role === 'admin' || role === 'estimator';

After (Configurable)

const canEdit = useCanPerform('edit_bid');

Backward Compatibility

The canEditBids property in RoleContext is preserved for backward compatibility but marked as deprecated. New code should use useCanPerform('edit_bid') instead.

Audit Logging

All permission changes are logged to the audit system:

ActionLogged Data
Permission UpdateRole additions/removals, permission key, modified by user
Reset to DefaultsAll permissions reset, timestamp, admin user
Auto-SeedingDefault permissions created on first access

View audit logs at Admin Panel → Audit Log tab.

Use Cases

Scenario: Only senior estimators should delete bids.

Solution:

  1. Go to Role Permissions
  2. Find delete_bid permission
  3. Uncheck all roles except ADMIN
  4. Only admins can now delete bids

Database Schema

model RolePermission {
id String @id @default(uuid())
permissionKey String @unique
permissionName String
description String?
category String @default("bids")
allowedRoles String[] @default(["ADMIN"])
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedBy String?
}

Troubleshooting

Changes not taking effect

Permissions are cached on the frontend. Have users refresh the page to see permission changes.

Cannot remove ADMIN from permission

This is by design. ADMIN role always has all permissions and cannot be restricted.

User sees 'Access Denied' error

Check:

  1. User's role in Admin → Users
  2. Permission settings for that role
  3. Audit log for recent permission changes

Best Practices

🔍

Test Permission Changes

Before deploying permission changes, test with a non-admin user to ensure expected behavior.

📖

Document Custom Permissions

If you create custom permission configurations, document them for future reference.

🕐

Use Audit Log

Review the audit log regularly to track who made permission changes and when.

🛡️

Principle of Least Privilege

Grant the minimum permissions necessary for each role to perform their job functions.

  • Module Permissions - Controls creation of items within modules (concrete mixes, equipment types, etc.)
  • User Management - Controls user accounts and service access
  • Audit Logging - Tracks all permission changes

Next Steps