Skip to main content
Version: 8.3

Extending record permissions

Level: intermediate
note

This functionality is available for Creatio 8.3.4 and later.

Out-of-the-box record-level access rights can implement any access condition. Users with the organizational or functional role can read, edit, or delete only the records their access rights allow. Learn more: Record permissions (user documentation).

To apply a condition through the out-of-the-box mechanism, Creatio calculates record-level access rights in advance and recalculates them whenever the record data changes — typically through business processes or triggers. Some access conditions are lightweight from a technical perspective and have little effect on Creatio performance. For example, comparing a single field value on the record. For a condition that depends on frequently changing data, or that applies to a large number of records, this recalculation can require significant computation and affect Creatio performance. Additionally, access rights can be temporarily out of date until the next recalculation completes since recalculating takes some time.

Since version 8.3.4, Creatio lets you extend the out-of-the-box record-level access rights with a condition, evaluated directly wherever Creatio checks access, instead of recalculating and storing access rights in advance. This lets you apply conditional access rights without the extra computation and without the risk of temporarily inconsistent access. A record permission extension is the class you implement to add a custom condition for the read, edit, or delete operation and one or more "Object" type schemas.

Typical scenarios for a record permission extension include:

  • a "Read" operation restricted by a business-specific record attribute
  • an "Edit" operation that depends on a simple condition
  • a "Delete" operation controlled by a rule for a small number of "Object" type schemas

Each of these scenarios is also possible with the out-of-the-box mechanism alone, but requires additional configuration effort, such as a business process or trigger that recalculates access rights.

Record permission extensions are managed by the UseRecordPermissionExtensions additional feature. Out of the box, the feature is registered and enabled, so record permission extensions extend record-level access rights for the read, edit, and delete operations. Record permission extensions do not extend object-level or column-level access rights. They also do not extend any operation outside the out-of-the-box record-rights logic.

Extension combination modes

For every operation, Creatio checks whether an extension is configured for the current operation and "Object" type schema. If it is configured, Creatio executes the extension and combines the returned condition with the out-of-the-box condition. Select the combination mode to extend the record-level access rights based on the business goals listed in the table below.

Business goal

Combination mode to use

Description

Replace the out-of-the-box access rights check

InsteadOf

Recommended mode. The extension condition alone determines access for the operation, and Creatio does not evaluate the out-of-the-box condition.

Narrow access beyond the out-of-the-box access rights

And

A record passes the check only if it satisfies both the out-of-the-box condition and the extension condition.

Broaden access beyond the out-of-the-box access rights

Or

A record passes the check if it satisfies either the out-of-the-box condition or the extension condition. We do not recommend using this mode, since Creatio must evaluate both the out-of-the-box and extension conditions, which can affect performance.

Structure of the record permission extension

Creatio implements the record permission extension through the classes and schemas listed in the table below.

Element

Description

DBSecurityEngine class

The main integration point for the record-level access rights extension. Creatio uses it to:

  • Determine whether the out-of-the-box record-rights flow is enough.
  • Check whether the UseRecordPermissionExtensions additional feature is enabled.
  • Request extensions from the IPermissionExtensionsProvider interface.
  • Execute the extension methods.
  • Convert the results into query conditions or right levels.
  • Combine the out-of-the-box and custom logic into the final result.

IPermissionExtensionsProvider interface

An abstraction between the DBSecurityEngine class and the extension configuration data. Creatio uses it to:

  • Return the applicable extension for the operation and "Object" type schema, together with the configured combination mode.
  • Hide how the configuration is read, selected, cached, and resolved into an extension class through the ClassFactory class.

CachedPermissionExtensionsProvider class

The concrete runtime implementation of IPermissionExtensionsProvider. It caches extension configuration so Creatio does not have to read and resolve it on every permission check. Creatio uses it to:

  • Lazily initialize a cache.
  • Read active extension metadata.
  • Group the configuration by the operation and "Object" type schema.
  • Select one applicable extension for each schema-operation pair.
  • Resolve the extension class through the ClassFactory class.
  • Clear the cache when the configuration changes.

"Record permission extension" (SysRecordPermissionExtension code) schema of the "Object" type

The configuration schema that tells Creatio which extension to use. Creatio uses it to:

  • Store one row per operation and target "Object" type schema, or several such schemas separated by ";"
  • Activate or deactivate a configuration row without deleting it.
  • Prioritize between several rows configured for the same schema and operation.

The extension parameters are stored in the Record permission extension lookup that based on the "Record permission extension" (SysRecordPermissionExtension code) object. Learn more about the lookup: Add the extension to Creatio.

SysRecordPermissionExtensionRepository class

Loads active rows from the "Record permission extension" (SysRecordPermissionExtension code) schema of the "Object" type. Creatio uses it to:

  • Expand the row into multiple schema-specific runtime options if the SchemaNames property lists several schemas, separated by ";"
  • Produce the resulting inputs the provider cache uses.

"SysRecordPermissionExtensionListener" (SysRecordPermissionExtensionListener code) schema of the "Source code" type

Guards configuration changes and invalidates the cache of the CachedPermissionExtensionsProvider class. Creatio uses it to:

  • Invalidate the cache of the CachedPermissionExtensionsProvider class after every insert, update, or delete of the "Record permission extension" (SysRecordPermissionExtension code) schema of the "Object" type.
  • Check the access right before it allows a change. The user needs either the "Can manage configuration elements" (CanManageSolution code) or "Access to "Access rights" workspace" (CanManageAdministration code) system operation. Out of the box, only users with the "System administrators" organizational role, or the "Developer" or "Administrator" role on ALM Portal, can change the configuration.

When the UseRecordPermissionExtensions additional feature is disabled, the CachedPermissionExtensionsProvider class does not initialize its cache or subscribe to synchronization events. Instead, the DBSecurityEngine class falls back to out-of-the-box record-right logic.

Selecting and resolving the applicable record permission extension

Creatio does not chain several extensions for the same operation and "Object" type schema. It selects and applies only one extension. Several active rows can exist for the same operation and schema, but configuration alone controls their priority — not the package load order or the class name.

Selecting and resolving the applicable record permission extension includes the following steps:

  1. Identify the active configuration rows for the target operation type and the "Object" type schema.

  2. Select the row with the lowest Position property value. If several rows have the same Position property value, Creatio selects the row with the latest CreatedOn property value instead.

  3. Call the TryGet() method of the ClassFactory class. This Creatio mechanism resolves a class by its registered binding name, passing the ExtensionName property value of the selected row as the binding name to resolve.

  4. Resolve the extension.

    • If the binding name matches a registered class, it uses that class as the applicable extension.
    • If the binding name does not match any registered class, it skips the row and logs a warning, even though the row stays active in the database.

Filtering records for the "Read" operation

Creatio uses this flow not only for reading records. It also uses this flow in other query-building scenarios that must restrict which records are available, including update-related flows.

Building the condition for the "Read" operation through the GetRecordsByRightCondition() method of the DBSecurityEngine class includes the following steps:

  1. Build the QueryCondition object, starting from the out-of-the-box record-right condition for the "Object" type schema.

  2. If the UseRecordPermissionExtensions additional feature is enabled and a "Read" permission extension exists for that schema:

    1. Call the GetReadRightCondition(UserConnection userConnection, PermissionExtensionContext context) method. The extension class implements this method through the IReadRecordPermissionExtension interface.
    2. Apply the returned QueryCondition object according to the combination mode configured for it.
  3. Attach the QueryCondition object to a Select object used for query construction.

  4. Transform the Select object into SQL text.

This flow builds a filter condition for selecting which records are available. Determining whether the current user can perform the "Read," "Edit," or "Delete" operation for a specific record is a different task.

Evaluating access rights for a specific record

This flow determines whether the current user can perform the "Read," "Edit," or "Delete" operation for this exact record.

Evaluating the read, edit, and delete operations through the GetEntitySchemaRecordRightLevel() method of the DBSecurityEngine class includes the following steps:

  1. Check whether the "Object" type schema is administered by records.

  2. Short-circuit to full access rights for privileged users, when appropriate.

  3. Select which record-level access rights to use.

    • If the UseRecordPermissionExtensions additional feature is disabled, uses the out-of-the-box access rights calculation.
    • If the UseRecordPermissionExtensions additional feature is enabled, resolves the "Read," "Edit," and "Delete" permission extensions configured for the schema of the "Object" type.
  4. Execute each applicable extension by building a correlated subquery that checks whether the extension condition matches the current record.

  5. Transform the extension conditions into per-operation right levels, adding the following flags to the extension-derived access rights set:

    • A matching "Read" permission extension adds the CanRead and CanChangeReadRight flags.
    • A matching "Edit" permission extension adds the CanEdit and CanChangeEditRight flags.
    • A matching "Delete" permission extension adds the CanDelete and CanChangeDeleteRight flags.
  6. Replace or merge the out-of-the-box access rights with the extension-derived access rights, using the combination mode configured for each operation. For example, the read operation may use the "And" mode, the edit operation may use the "InsteadOf" mode, and the delete operation may have no extension at all. This keeps each operation independent.

Read, edit, and delete may all have an applicable extension. If each operation has an applicable extension and uses the "InsteadOf" combination mode, Creatio returns only the extension-derived access rights for this record. It does not merge them with the out-of-the-box access rights. This behavior is both an optimization and a semantic rule.

Invalidating the cache and synchronizing web farm nodes

The cache of the CachedPermissionExtensionsProvider class is lazy and persistent. Creatio needs a reliable way to invalidate it after a configuration change. The following actions complete after an insert, update, or delete of the "Record permission extension" (SysRecordPermissionExtension code) schema of the "Object" type:

  1. The SysRecordPermissionExtensionListener class clears the local cache of the CachedPermissionExtensionsProvider class. The next request rebuilds the cache from fresh configuration data.
  2. If your Creatio instance uses a web farm, the CachedPermissionExtensionsProvider class also publishes a synchronization message through a publish/subscribe channel.
  3. Other web farm nodes receive the message and clear their own local caches, so all nodes apply configuration changes consistently.

Without this step, one node could keep using outdated extension metadata after another node had already applied a change.

Falling back to out-of-the-box behavior

Creatio falls back to out-of-the-box behavior in the following cases:

  • If no extension exists for the operation and "Object" type schema, the out-of-the-box access rights logic continues to apply.
  • If the extension method returns null, Creatio treats the result as not applicable, as if no extension were configured for that operation in this evaluation.
  • If Creatio cannot resolve the selected extension name through the ClassFactory class, it skips the extension and continues with the out-of-the-box behavior.

These fallback rules reduce the risk of hard failures in the record-level access rights extension.

See also

Implement a custom record permission extension

Record permission extension patterns