* @param array $record
* @param int|null $userID
* Contact ID of the active user (whose access we must check). NULL for anonymous.
- * @param bool $granted
* @return bool
+ * TRUE if granted. FALSE if prohibited. NULL if indeterminate.
*/
- public static function checkAccess(string $entityName, string $action, array $record, $userID, $granted = TRUE): bool {
+ public static function _checkAccess(string $entityName, string $action, array $record, $userID): ?bool {
$groupName = substr($entityName, 0, 7) === 'Custom_' ? substr($entityName, 7) : NULL;
if (!$groupName) {
// $groupName is required but the function signature has to match the parent.
$cid = CRM_Core_DAO::singleValueQuery("SELECT entity_id FROM `$tableName` WHERE id = " . (int) $record['id']);
}
- // Dispatch to hook
- $granted = NULL;
- CRM_Utils_Hook::checkAccess("Custom_$groupName", $action, $record, $userID, $granted);
- if ($granted === NULL) {
- $granted = \Civi\Api4\Utils\CoreUtil::checkAccessDelegated('Contact', 'update', ['id' => $cid], $userID);
- }
- return $granted;
+ return \Civi\Api4\Utils\CoreUtil::checkAccessDelegated('Contact', 'update', ['id' => $cid], $userID);
}
}
* The record should provide an 'id' but may otherwise be incomplete; guard accordingly.
* @param int|null $userID
* Contact ID of the active user (whose access we must check). NULL for anonymous.
- * @param bool $granted
- * Initial value (usually TRUE, but the API might pass FALSE if gatekeeper permissions fail)
- *
* @return bool
+ * TRUE if granted. FALSE if prohibited. NULL if indeterminate.
*/
- public static function checkAccess(string $entityName, string $action, array $record, $userID, $granted = TRUE): bool {
+ public static function checkAccess(string $entityName, string $action, array $record, $userID): ?bool {
// Ensure this function was either called on a BAO class or a DAO that has no BAO
if (!$entityName ||
(!strpos(static::class, '_BAO_') && CRM_Core_DAO_AllCoreTables::getBAOClassName(static::class) !== static::class)
) {
throw new CRM_Core_Exception('Function checkAccess must be called on a BAO class');
}
- // Dispatch to protected function _checkAccess in this BAO
- if ($granted && method_exists(static::class, '_checkAccess')) {
- $granted = static::_checkAccess($entityName, $action, $record, $userID);
+ if (method_exists(static::class, '_checkAccess')) {
+ return static::_checkAccess($entityName, $action, $record, $userID);
+ }
+ else {
+ return TRUE;
}
- // Dispatch to hook
- CRM_Utils_Hook::checkAccess($entityName, $action, $record, $userID, $granted);
- return $granted;
}
/**
* The record should provide an 'id' but may otherwise be incomplete; guard accordingly.
* @param int|null $contactID
* Contact ID of the active user (whose access we must check).
- * @param bool $granted
+ * @param bool|null $granted
+ * TRUE if granted. FALSE if prohibited. NULL if indeterminate.
*/
- public static function checkAccess(string $entity, string $action, array $record, ?int $contactID, bool &$granted) {
+ public static function checkAccess(string $entity, string $action, array $record, ?int $contactID, ?bool &$granted) {
self::singleton()->invoke(['entity', 'action', 'record', 'contactID', 'granted'], $entity, $action, $record,
$contactID, $granted, self::$_nullObject,
'civicrm_checkAccess'
* @throws \Civi\API\Exception\UnauthorizedException
*/
public static function checkAccessRecord(\Civi\Api4\Generic\AbstractAction $apiRequest, array $record, ?int $userID) {
- $granted = TRUE;
// For get actions, just run a get and ACLs will be applied to the query.
// It's a cheap trick and not as efficient as not running the query at all,
// but BAO::checkAccess doesn't consistently check permissions for the "get" action.
if (is_a($apiRequest, '\Civi\Api4\Generic\DAOGetAction')) {
- $granted = $granted && $apiRequest->addSelect('id')->addWhere('id', '=', $record['id'])->execute()->count();
+ return (bool) $apiRequest->addSelect('id')->addWhere('id', '=', $record['id'])->execute()->count();
}
- else {
- // If entity has a BAO, run the BAO::checkAccess function, which will call the hook
- $baoName = self::getBAOFromApiName($apiRequest->getEntityName());
- if ($baoName) {
- $granted = $baoName::checkAccess($apiRequest->getEntityName(), $apiRequest->getActionName(), $record, $userID, $granted);
- }
- // Otherwise, call the hook directly
- else {
- \CRM_Utils_Hook::checkAccess($apiRequest->getEntityName(), $apiRequest->getActionName(), $record, $userID, $granted);
- }
+
+ $granted = NULL;
+ \CRM_Utils_Hook::checkAccess($apiRequest->getEntityName(), $apiRequest->getActionName(), $record, $userID, $granted);
+ $baoName = self::getBAOFromApiName($apiRequest->getEntityName());
+ if ($granted === NULL && $baoName) {
+ $granted = $baoName::checkAccess($apiRequest->getEntityName(), $apiRequest->getActionName(), $record, $userID);
}
return $granted;
}
* @param string $action
* @param array $record
* @param int|null $contactID
- * @param bool $granted
+ * @param bool|null $granted
*
* @throws \CRM_Core_Exception
*/
-function financialacls_civicrm_checkAccess(string $entity, string $action, array $record, ?int $contactID, bool &$granted) {
+function financialacls_civicrm_checkAccess(string $entity, string $action, array $record, ?int $contactID, ?bool &$granted) {
if (!financialacls_is_acl_limiting_enabled()) {
return;
}
* @param bool $granted
* @see \CRM_Utils_Hook::checkAccess()
*/
- public function hook_civicrm_checkAccess(string $entity, string $action, array $record, ?int $contactID, bool &$granted) {
+ public function hook_civicrm_checkAccess(string $entity, string $action, array $record, ?int $contactID, ?bool &$granted) {
$key = "{$entity}::{$action}";
if (isset($this->checkAccessGrants[$key])) {
$granted = $this->checkAccessGrants[$key];