Skip to main content

Overview

MLM CMMS uses a Role-Based Access Control (RBAC) system to manage user permissions. Each user is assigned a single role, and each role has a collection of permissions that determine what actions the user can perform.
Managing roles requires rbac:manage_roles. Managing permissions requires rbac:manage_permissions.

Accessing Roles & Permissions

Navigate to Administration → Settings and select the “Roles” or “Permissions” tab.

RBAC Architecture

Roles

A role is a named collection of permissions. Users are assigned to roles, and inherit all permissions from that role. Role Properties:
FieldTypeDescription
idIntegerUnique role identifier
nameStringRole name (e.g., “Administrador”, “Técnico”)
descriptionTextOptional description of the role’s purpose
created_atTimestampCreation date

Permissions

A permission is a specific action on a resource, represented by a permission code:
{resource}:{action}
Examples:
  • users:read → View users
  • users:full_access → Create and edit users
  • work_orders:create → Create work orders
  • rbac:manage_roles → Manage roles
Permission Properties:
FieldTypeDescription
idUUIDUnique permission identifier
codeStringPermission code (e.g., users:read)
resourceStringResource name (e.g., users, work_orders)
actionStringAction type (e.g., read, create, delete)
labelStringHuman-readable label
descriptionTextOptional description
is_activeBooleanWhether the permission is enabled

Role-Permission Mapping

The relationship between roles and permissions is managed through the role_permissions table:
role_permissions (
  role_id integer,
  permission_id uuid,
  PRIMARY KEY (role_id, permission_id)
)

Permission Registry

The frontend maintains a permission registry in src/rbac/permissionRegistry.ts. This registry defines all available permissions and is used to synchronize permissions to the database.

Resource Categories

RBAC

  • rbac:manage_permissions
  • rbac:manage_roles

Users

  • users:read
  • users:create
  • users:update
  • users:full_access
  • users:cancel
  • users:delete

Work Orders

  • work_orders:read
  • work_orders:read_own
  • work_orders:create
  • work_orders:full_access
  • work_orders:cancel
  • work_orders:delete

Work Requests

  • work_requests:read
  • work_requests:full_access
  • work_requests:cancel
  • work_requests:delete

Assignees (Technicians)

  • assignees:read
  • assignees:full_access
  • assignees:cancel
  • assignees:delete

Locations

  • locations:read
  • locations:create
  • locations:update
  • locations:delete
  • locations:disable
  • locations:full_access

Assets

  • assets:read
  • assets:create
  • assets:update
  • assets:delete
  • assets:disable
  • assets:full_access

Inventory

  • inventory:read
  • inventory:create
  • inventory:update
  • inventory:delete
  • inventory:approve
  • inventory:cancel
  • inventory:work
  • inventory:full_access

Special Incidents

  • special_incidents:read
  • special_incidents:full_access
  • special_incidents:disable
  • special_incidents:delete

Announcements

  • announcements:read
  • announcements:create
  • announcements:full_access
  • announcements:disable
  • announcements:delete

Society

  • society:read
  • society:create
  • society:full_access
  • society:disable
  • society:delete

Reports

  • reports:read

Common Permission Actions

ActionDescription
readView records
read_ownView only records owned by the user
createCreate new records
updateEdit existing records
deleteDelete records
full_accessCreate, read, update, and sometimes delete
cancelActivate/deactivate or cancel records
disableDeactivate records
approveApprove or publish records
assignAssign resources to other entities
workPerform work-related actions (e.g., reserve inventory)
manage_rolesManage roles (RBAC)
manage_permissionsManage permissions (RBAC)

Role Management Workflows

Creating a Role

1

Navigate to Roles

Go to Administration → Settings → Roles.
2

Click 'Crear rol'

Opens the role creation form.
3

Fill in Role Details

  • Name: Unique role name (e.g., “Supervisor de Mantenimiento”)
  • Description (optional): Purpose or scope of the role
4

Save

Click “Crear”. The role is created with no permissions.

Assigning Permissions to a Role

1

Locate the Role

In the Roles tab, find the role you want to edit.
2

Click 'Editar permisos'

Opens the role editor interface.
3

Select Permissions

Permissions are grouped by resource. For each resource:
  • Seleccionar todo: Check all permissions in the group
  • Quitar todo: Uncheck all permissions in the group
  • Individual checkboxes: Select specific permissions
4

Save Changes

Click “Guardar cambios”. The system calls set_role_permissions RPC to update the role_permissions table.
Changes to role permissions take effect immediately. Users will inherit the updated permissions on their next API call.

Viewing Users in a Role

1

Open the Role List

Navigate to Administration → Settings → Roles.
2

Click 'Usuarios'

Opens a modal showing all users assigned to the role.
3

Manage User Assignments

In the modal, you can:
  • View the list of users with that role
  • Remove users from the role
  • Assign new users to the role

Deleting a Role

Deleting a role will remove all permission assignments. Users with that role will lose all permissions.
1

Check for Dependencies

Ensure no users are actively using the role, or reassign them first.
2

Click 'Eliminar'

On the role’s row in the Roles tab.
3

Confirm Deletion

Confirm the action in the dialog.

Permission Management

Synchronizing Permissions

The permission registry in the frontend must be synchronized with the database:
1

Navigate to Permissions Tab

Administration → Settings → Permissions.
2

Click 'Sincronizar permisos'

This button calls the sync_permissions_from_registry RPC function.
3

Review Sync Results

The system will:
  • Insert new permissions from the registry
  • Update existing permission labels/descriptions
  • Mark missing permissions as inactive
Always synchronize permissions after updating the permissionRegistry.ts file.

Viewing Permission Details

The Permissions tab shows:
  • Code: Permission identifier (e.g., users:read)
  • Resource: Resource category
  • Action: Action type
  • Label: Human-readable name
  • Description: Detailed explanation
  • Status: Active/Inactive
Use the search bar to filter by code, label, or description.

Using Permissions in Code

Frontend Permission Checks

Component-Level Access Control

import { Can } from '../rbac/PermissionsContext';

<Can perm="users:create">
  <button onClick={createUser}>Create User</button>
</Can>

Hook-Based Permission Checks

import { useCan } from '../rbac/PermissionsContext';

const MyComponent = () => {
  const canEdit = useCan('work_orders:update');
  const canDelete = useCan('work_orders:delete');
  
  return (
    <div>
      {canEdit && <button onClick={handleEdit}>Edit</button>}
      {canDelete && <button onClick={handleDelete}>Delete</button>}
    </div>
  );
};

Typed Permission Codes

import { code, RESOURCES } from '../rbac/permissionRegistry';

const myPermission = code(RESOURCES.users, 'read'); // "users:read"

Backend Permission Checks (RLS Policies)

PostgreSQL Row-Level Security policies enforce permissions at the database level:
CREATE POLICY "users_select_rbac" ON users
  FOR SELECT
  USING (
    current_user_has_permission('users:read'::text) OR
    current_user_has_permission('users:full_access'::text)
  );
Never rely solely on frontend permission checks. Always enforce permissions with RLS policies or backend logic.

Database Functions

set_role_permissions

Assigns permissions to a role:
set_role_permissions(
  p_role_id integer,
  p_perm_codes text[]
)
Behavior:
  1. Deletes all existing permissions for the role
  2. Inserts new permission assignments based on p_perm_codes

sync_permissions_from_registry

Synchronizes permissions from the frontend registry:
sync_permissions_from_registry(
  p_permissions jsonb[]
)
Behavior:
  1. Inserts new permissions not in the database
  2. Updates labels/descriptions for existing permissions
  3. Marks permissions not in the registry as is_active = false

current_user_has_permission

Helper function used in RLS policies:
current_user_has_permission(permission_code text) RETURNS boolean
Returns true if the current authenticated user has the specified permission.

Best Practices

Principle of Least Privilege

Grant users only the permissions they need to perform their job functions.

Use Roles, Not Direct Assignments

Always assign users to roles rather than granting permissions individually.

Sync Permissions Regularly

After deploying code changes that add new permissions, sync the permission registry.

Document Custom Roles

Use the role description field to document the purpose and scope of custom roles.

Test Permission Changes

Verify that users can (and cannot) perform expected actions after role/permission changes.

Audit Permission Usage

Periodically review role assignments and remove unused permissions.

Troubleshooting

”No tienes permiso para…”

Cause: The user’s role does not include the required permission. Solution:
  1. Verify the user’s role assignment
  2. Check if the role has the required permission
  3. If not, edit the role to add the permission

Permission Not Appearing in Role Editor

Cause: The permission is not synchronized from the registry. Solution:
  1. Go to Administration → Settings → Permissions
  2. Click “Sincronizar permisos”
  3. Verify the permission appears in the list

Changes Not Taking Effect

Possible causes:
  1. Frontend cache: Refresh the page or clear browser cache
  2. Permission context not refreshed: Log out and log back in
  3. RLS policy not updated: Redeploy database migrations

User Has No Permissions After Role Assignment

Cause: The role has no permissions assigned. Solution: Edit the role and assign the necessary permissions.