I've recently been exploring the $permissions array that drives API actions and extracted the metadata from the logic to allow displaying as a nice table.

The CRM_Utils_Hook::alterAPIPermissions($entity, $action, $params, $permissions) hook further modifies this permission matrix before it gets passed to function check($permissions)

The grid is sparse in some places and references:

What is the over-arching strategic architecture behind this? (to the extent that one exists at least)

Or what should it be?

1 Answer 1


I like the table.

It would be really cool if that information were available inline as part of the "API Explorer" -- eg when you inspect the Activity.create API, you'd be able to further review the required permissions.

The permissions in the table you describe are generally coarse-grained, entity-oriented permissions. Quintessential examples are "edit all contacts" or "delete mailings". These depend only on the entity name and action name.

The other items that you're asking about could be categorized as fine-grained authorizations. These depend on the specific data involved. However, they slice-and-dice differently (applying different rules to different data in different use-cases).

  • DynamicFKAuthorization is applied to Attachment API. Every attachment is subordinate to another record (like Mailing #123 or Contact #456 or Activity #789). Your permission to CRUD an Attachment depends on your permission to CRUD the targeted record. The basic idea is delegation. For example, the permissions for Attachment.create(entity_type=mailing,entity_id=123) are determined by delegating to the authorization logic of Mailing.create(id=123).
  • _civicrm_api3_check_edit_permissions() is nominally applied to many API entities, but in reality only applies to Phone, Email, Address, IM, OpenID, and Website records. All of these are subordinate to Contact. Your permission to CRUD a Phone depends on your permission to CRUD the contact record.
  • BAO::addSelectWhereClause is nominally applied to most API entities. On its own, it doesn't do much, but it can be adapted via subclass or hook. It allows to limit visibility into entities based on their data. For example, a listener might define a rule that "the current user can only query activities of type Meeting".

These three examples have some similarities (e.g. they're all fine-grained), and they have some arbitrary differences (e.g. procedural style vs OOP style), but they also address qualitatively different scenarios. I don't think their original authors intended/expected them to be compared in this way, so it wouldn't be accurate to describe them with an "over-arching strategic architecture". However, if someone finds an elegant way to make these more-similar, that would be great.

(Edit) Returning to your original question -- "Why is the matrix sparse?" The matrix only addresses cases where we expect coarse-grained/entity-oriented access-control to serve the business-needs of typical organizations. In cases where we expect the business needs to be more fine-grained/data-oriented, you need to reference more nuanced logic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.