Back to Home

RBAC with statuses in JMatrixPlatform

JMatrixPlatform combines RBAC with object statuses for granular access control. Filtering is applied at SQL level, statuses are audited. Examples of role, policy configuration and promote/demote methods are provided.

Status-role RBAC in JMatrix: code and practice
Advertisement 728x90

Status-Based RBAC in JMatrixPlatform: Lifecycle-Aware Access Control

JMatrixPlatform implements Role-Based Access Control (RBAC) by binding permissions to object statuses. Every object has a type and a lifecycle — a defined sequence of statuses that reflect its current state. When an object is created, its type and associated lifecycle are specified; the initial status defaults to the first in that lifecycle or is explicitly overridden in the createAction.

A single object type can support multiple lifecycles. For example:

| Object | Type | Lifecycle | Status | Available Next Statuses |

Google AdInline article slot

|--------|------|-----------|--------|--------------------------|

| Obj1 | Type1| LC1 | Stat1 | Stat1*, Stat2 |

| Obj2 | Type1| LC2 | Stat4 | Stat1–4* |

Google AdInline article slot

| Obj3 | Type1| LC3 | Stat2 | Stat1–3* |

Typical lifecycles include:

  • Documentation: Draft → Published → Review → Archived → Issued
  • Reference data: New → Active → Deprecated

Status transitions occur via promote (forward) or demote (backward), with full audit logging in the object_states table:

Google AdInline article slot
create table object_states (
    object_id uuid not null,
    policy_state varchar(100) not null,
    user_id uuid not null,
    state_start timestamp not null,
    state_end timestamp
);

Audit logs enable process delay analysis: SELECT user_id FROM object_states WHERE policy_state = ? AND (state_end - state_start) >= ?.

Configuring Roles and Policies

Roles extend JRole:

@JModelPart
public final class ARLReferenceAdmin extends JRole {
  public final static ARLReferenceAdmin ROLE = new ARLReferenceAdmin();

  @Override
  public Set<JRole> getParents() {
    return Set.of(ARLRefDesigner.ROLE, ARLRefChangeManagementAdmin.ROLE, ARLRefApprover.ROLE);
  }

  @Override
  public String getDescription() {
    return "Reference Data Administrator";
  }
}

Lifecycles extend JPolicy:

@JModelPart
public final class ALCReference extends JPolicy {
  public final static ALCReference POLICY = new ALCReference();

  @Override
  public Set<JType> getTypes() {
    return Set.of(ATPReference.TYPE);
  }
  
  @Override
  public List<JState> getStates() {
    return List.of(New.STATE, Active.STATE, Inactive.STATE);
  }

  public static final class New extends JPolicy.JState {
    public static final New STATE = new New();
    @Override
    public Set<RoleAccess> getAccess() {
      return Set.of(new RoleAccess(ARLReferenceAdmin.ROLE, AccessType.ALL));
    }
  }

  public static final class Active extends JPolicy.JState {
    public static final Active STATE = new Active();
    @Override
    public Set<RoleAccess> getAccess() {
      return Set.of(
        new RoleAccess(JPublic.ROLE, AccessType.READ),
        new RoleAccess(ARLReferenceAdmin.ROLE, AccessType.PROMOTE, AccessType.DEMOTE));
    }
  }

  public static final class Inactive extends JPolicy.JState {
    public static final Inactive STATE = new Inactive();
    @Override
    public Set<RoleAccess> getAccess() {
      return Set.of(
        new RoleAccess(JPublic.ROLE, AccessType.READ),
        new RoleAccess(ARLReferenceAdmin.ROLE, AccessType.DEMOTE));
    }
  }
}

AccessType values:

  • ALL: Full control
  • READ: View only
  • CREATE: Create new instances
  • MODIFY: Edit existing data
  • DELETE: Remove objects
  • RELEASE: Version management
  • PROMOTE: Advance to next status
  • DEMOTE: Revert to previous status
  • CHECKIN: Upload files
  • CHECKOUT: Download files

Object creation:

JDomainObject obj = new JDomainObject();
obj.create(ctx, ATPDocuments.TYPE, ALCDocument.POLICY);

The platform validates CREATE permission against the initial status. Status transitions use:

obj.promote(ctx); // forward
obj.demote(ctx);  // backward

Database-Level Authorization Mechanisms

JWT roles integrate with Keycloak, and row-level filtering is applied directly in SQL queries — data never leaves the database without authorization.

Maximum Access

JSystemAdmin bypasses all checks for maximum throughput.

Status-Based Access

Example access matrix:

| Role | New | Active | Deprecated |

|-------------------|------------|-----------------------|--------------|

| ARLReferenceAdmin | ALL | READ, PROMOTE, DEMOTE | READ, DEMOTE |

| JPublic | #NOACCESS | READ | READ |

For JPublic: WHERE policy_state IN ('ALCReference.Active', 'ALCReference.Inactive').

For administrators: no status restrictions. Optimization note: ~100 statuses max per policy; temp-table-based filtering under consideration.

Property-Based Filtering

In development. Recursive relationship traversal for access checks is currently inefficient.

Key Takeaways

  • Statuses are natively embedded into RBAC — enabling fine-grained, non-destructive access control.
  • Full status audit trail in object_states supports process analytics and compliance reporting.
  • SQL-level filtering ensures sensitive data never leaves the database without explicit authorization.
  • Every promote/demote action is logged with user ID and timestamp.
  • Seamless Keycloak role synchronization into JWT tokens.

— Editorial Team

Advertisement 728x90

Read Next